实例属性通常在类上注释:
class Foo:
x: int
def __init__(self, x):
self.x = x
Foo(0).x
这有效,并且 mypy 不会报告任何问题。然而,当实例属性是
Callable
时,mypy 开始抱怨:
from typing import Callable
class Foo:
func: Callable[[], int]
def __init__(self, func):
self.func = func
Foo(lambda: 0).func()
我收到以下错误:
test.py:11: error: Attribute function "func" with type "Callable[[], int]" does not accept self argument
Found 1 error in 1 file (checked 1 source file)
由于该函数没有在类上定义,而仅存储在实例字典中,因此在属性查找期间它不会绑定到实例(简而言之:上面的代码片段有效)。所以我不明白为什么 mypy 会抱怨这个。是否有另一种方法来输入此类实例级函数的提示?
这目前在 mypy 中被破坏,因为它假设您正在创建一个方法,这是相关问题https://github.com/python/mypy/issues/708.
在 init 中键入函数可以正常工作,因为它不会认为它是类上的方法,以下代码正确地通过了类型检查,并且
func
的类型是从参数推断出来的。如果参数不可行,也可以直接输入属性赋值。
from collections.abc import Callable
class Foo:
def __init__(self, func: Callable[[], int]):
self.func = func
reveal_type(Foo(lambda: 0).func)
###OUTPUT###
file.py:7: note: Revealed type is "def () -> builtins.int"
可以在问题中找到并避免在 init 中分配的另一种解决方法是使用回调
Protocol
,如下所示:
from typing import Protocol
class FuncCallback(Protocol):
def __call__(self, /) -> int:
...
class Foo:
func: FuncCallback
def __init__(self, func):
self.func = func
这使得
func
成为一个 FuncCallback
协议,在调用时不需要任何参数,并返回像你的 int
一样的 Callable
。