如何键入提示功能与numpy兼容
example.py
的源代码:
from typing import Union, Any
import numpy as np
Number = Union[int, float, np.floating[Any]]
def add_one(num: Number) -> Number:
return num + 1
inputs = [1, 2, 3]
outputs = [add_one(n) for n in inputs]
avg = np.mean(outputs)
运行mypy:
mypy example.py
src/example.py:14: error: Argument 1 to "mean" has incompatible type "List[Union[float, floating[Any]]]"; expected "Union[_SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[Union[bool, int, float, complex, str, bytes]]]"
Found 1 error in 1 file (checked 1 source file)
我可以将所有内容更改为 np.doploing [any]
解决了numpy问题代码> np.float32(...):
from typing import Any
import numpy as np
def add_one(num: np.floating[Any]) -> np.floating[Any]:
return num + 1
inputs = [1, 2, 3]
outputs = [add_one(np.float32(n)) for n in inputs]
avg = np.mean(outputs)
是否有正确的方法键入 add_one
函数,以便其输出与numpy函数兼容,例如 np.mean
没有与python原始类型的兼容性?最终目标是能够这样使用:
inputs = [1, 2, 3]
outputs = [add_one(n) for n in inputs]
avg = np.mean(outputs)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
Mypy对复杂类型的层次结构过于严格。 (可能是由于
numpy.mean.mean
的第1 arg。 ,只是一个林格错误,很难告诉谁应该归咎于谁。
您有几个选项:
1。只需忽略调用
earne
avg = avg = np.mean(outputs)#类型:ignore
a
list list list 的
avg = avg = avg = avg = avg = avg = avg = avg = a a [t] 应该是array_like
,因为numpy
可以处理它。但是由于某种原因,mypy
有时无法使自定义类型的等价 。代码是正确的,因此您可以只是忽略该调用的类型。2。保持类型提示原样。使用
np.Array
altought
mypy
未能识别list [t]
是array_like
用于复杂和抽象类型<代码> t ,它不会抱怨np.Array
以下编辑脚本在这两个变体中都可以正常工作,并且没有任何错误,也没有发出Mypy的警告:
运行:
mypy 。
在1个源文件中找到的问题
请注意,所有 numpys的示例 for
sane
passnp np。 Array
而不是list
作为 a 属性3。定义自定义
协议
支持Aritmethic和数字操作以及转换为原始类型和numpy类型是一个好主意,确保它与其他数字类表现良好,我使用
real 类,因为它非常谨慎兼容,但您可以进一步限制它。
number
package然后,您应该能够这样使用它:
运行:
mypy ./example.py.py
输出:
成功:1源文件中没有发现任何问题
4。定义自定义实现
list [number]
明确array_like
。替代方案,如果您正在运行python&gt; = 3.12,并且提供支持 pep 695 您可以定义一个
列表
实现array
接口的子类型:运行:
mypy ./example.py.py.py
输出:
成功:1个源中未发现任何问题文件
说明
问题是列表的mypys处理[数字],而不是
按照 numpy的参考
numpy.mean.mean
定义为numpy.mean.mean(a,axis = none,dype = none,none,none,out of = none,keepdims =&lt; no value&gt;, *,其中=&lt; no value&gt;)
其中a
a 是类型array_like
in numpy,numpy定义
array_like
be:当
您查看
numpy.core.fromnumeric.pyi
的重载函数的定义平均值
您发现有6个实际的过载平均值
:那么...什么给?
list [number]
应该与array_like
兼容,对吗?好吧,让我们仔细观察Mypy给出的错误:
您会注意到,尽管它显然是引用了晦涩的抽象类型的结合(也可能是自动生成的类型),联盟中的主要类型是
_supportArray
,这是一个非常抽象的协议在numpy._typing._array_like
中定义的:我们要寻找的目标应该是:
€this是问题! linter期望
_supportSarray
bool _
,integer [any]
或floing> floating [any]
如果
>数字
其中union [bool_ |整数[任何] |浮动[任何]
,mypy不会抱怨。但是这是当前实现numpy 的错误,预期类型应为
_supportSarray [任何]
作为文档所述。MyPy is beeing too strict on complex type hierarchy. (possibly due to an ill-defined type for
numpy.mean
's 1st arg.) (( maybe a bug in MyPy's stubs/type definitions?))The code runs, is just a linter error, hard to tell who's to blame.
You have a few options:
1. Just ignore typecheck for the call to
mean
avg = np.mean(outputs) # type: ignore
A
List[T]
should be anarray_like
, asNumPy
can handle it. But for some reasonMyPy
sometimes fails to make that equivalence for custom types. The code is correct, so you could just ignore types for that call.2. Keep type hint as-is. Use
np.array
Altought
MyPy
fails to recognize thatList[T]
isarray_like
for complex and abstract typesT
, it won't complain about annp.array
The following edited script works fine in both variations, and gives no errors nor warnings from MyPy:
Running:
mypy ./example.py
Output:
Success: no issues found in 1 source file
Running:
mypy ./example.py
Output:
Success: no issues found in 1 source file
Note that all of Numpys's examples for
mean
passnp.array
and notList
asa
attribute3. Define custom
Protocol
that supports aritmethic and numerical operations and conversion to primitive types and Numpy typesIt'd be a good idea to ensure it behaves well with other number classes, I've used
number
package'sReal
class, as it is very braodly compatible, but you could further constrian it.Then you should be able to use it like this:
Running:
mypy ./example.py
Output:
Success: no issues found in 1 source file
4. Define custom implementation of
List[Number]
that is explicitlyarray_like
.Alternative, if you're running Python >= 3.12, and MyPy >= 1.12 which offers support for PEP 695 you could define a
list
subtype that implements thearray
interface:Running:
mypy ./example.py
Output:
Success: no issues found in 1 source file
Explanation
The problem is MyPys handling of the List[Number], not the underlying types contained in it
As per Numpy's reference
numpy.mean
is defined asnumpy.mean(a, axis=None, dtype=None, out=None, keepdims=<no value>, *, where=<no value>)
wherea
is of typearray_like
In it's glossary, Numpy defines
array_like
to be:And
When you look at the
numpy.core.fromnumeric.pyi
's definitions for overloaded functionmean
you find that there are 6 actual overloads ofmean
:So... what gives?
List[Number]
should be compatible witharray_like
, right?Well, let's look closely at the error MyPy gives:
You'll notice that althought it's clearly referincing a Union of obscure abstract types (and possibly auto-generated types as well) the primary type in the Union is
_SupportsArray
, which is a pretty abstract protocol defined innumpy._typing._array_like
:The target we're looking for should be:
¡That's the problem! linter expects a
_SupportsArray
ofbool_
,integer[Any]
, orfloating[Any]
If
Number
whereUnion[bool_ | integer[Any] | floating[Any]
, MyPy wouldn't complain.But that's a bug in current implementation of NumPy, the expected type should be
_SupportsArray[Any]
as the documentation states.在确保最大灵活性的同时,解决此
mypy
问题的一种更强大的方法是使用python的协议
从键入
,它允许更精确的类型提示值支持数值操作。您可以定义自定义
supportsnumericOps
协议A more robust way to solve this
MyPy
issue while ensuring maximum flexibility is to use Python’sProtocol
fromtyping
, which allows for more precise type hinting for values that support numerical operations.You can define a Custom
SupportsNumericOps
Protocol出现问题是因为
np.mean
期望输入与numpy
数组兼容,但是当您使用时,
add_one
函数返回混合类型。联合[int,float,np。您还将返回类型设置为数字,这可能不是输入此功能的最精确或最有用的方法,尤其是在使用Numpy时。
我认为,与
numpy
函数兼容键入提示的最准确方法是使用np.ndarray
与dtype
参数覆盖该参数,该参数涵盖预期数字类型。示例代码:
输出:
The problem arises because
np.mean
expects inputs to be compatible withNumPy
arrays, but theadd_one
function returns mixed types when you useUnion[int, float, np.floating[Any]]
.You also set the return type to Number which might not be the most precise or helpful way to type hint this function, especially when working with NumPy.
In my opinion, the most accurate way to type hints for compatibility with
NumPy
functions is to usenp.ndarray
with adtype
argument that covers the expected numeric types.Example Code:
Output:
只需使用
number = union [int,float]
不会丢下任何mypy错误。Just using
Number = Union[int, float]
doesn't throw any mypy error.