回调协议——我们什么时候需要双下划线前缀?
Callback protocols - when do we need the double underscore prefix?
Callback protocols and :py:data:~typing.Callable
types can be used
interchangeably. Keyword argument names in :py:meth:__call__ <object.__call__>
methods must be identical, unless a double
underscore prefix is used. For example:
typing_extensions import Protocol
T = TypeVar('T')
class Copy(Protocol):
def __call__(self, __origin: T) -> T: ...
copy_a: Callable[[T], T] copy_b: Copy
copy_a = copy_b # OK copy_b = copy_a # Also OK ```
但是,如果我们删除 __origin
之前的双下划线前缀,这个例子也可以工作。例如
$ cat t.py
from typing import Callable, TypeVar
from typing_extensions import Protocol
T = TypeVar('T')
class Copy(Protocol):
def __call__(self, origin: T) -> T: ...
copy_a: Callable[[T], T]
copy_b: Copy
copy_a = copy_b # OK
copy_b = copy_a # Also OK
$ mypy t.py
Success: no issues found in 1 source file
所以,这个例子对我来说不是很清楚。我们什么时候需要双下划线前缀?
可以使用命名参数代替匿名参数,因此协议用作 Callable 的值。第一个赋值 copy_a = copy_b
默默地将 copy_a
提升为 Copy
,然后有效地赋值给 copy_b: Copy
.
...
copy_a = copy_b # copy_a is a Copy now!
copy_b = copy_a # assign copy_a: Copy to copy_b: Copy
reveal_type(copy_a) # Revealed type is 'aaa_testbed.Copy'
交换赋值意味着 copy_b = copy_a
发生而 copy_a
仍然是匿名类型。这会触发预期的错误:
...
copy_b = copy_a # Incompatible types in assignment (expression has type "Callable[[T], T]", variable has type "Copy")
copy_a = copy_b
Callback protocols and :py:data:
~typing.Callable
types can be used interchangeably. Keyword argument names in :py:meth:__call__ <object.__call__>
methods must be identical, unless a double underscore prefix is used. For example:typing_extensions import Protocol T = TypeVar('T') class Copy(Protocol): def __call__(self, __origin: T) -> T: ... copy_a: Callable[[T], T] copy_b: Copy copy_a = copy_b # OK copy_b = copy_a # Also OK ```
但是,如果我们删除 __origin
之前的双下划线前缀,这个例子也可以工作。例如
$ cat t.py
from typing import Callable, TypeVar
from typing_extensions import Protocol
T = TypeVar('T')
class Copy(Protocol):
def __call__(self, origin: T) -> T: ...
copy_a: Callable[[T], T]
copy_b: Copy
copy_a = copy_b # OK
copy_b = copy_a # Also OK
$ mypy t.py
Success: no issues found in 1 source file
所以,这个例子对我来说不是很清楚。我们什么时候需要双下划线前缀?
可以使用命名参数代替匿名参数,因此协议用作 Callable 的值。第一个赋值 copy_a = copy_b
默默地将 copy_a
提升为 Copy
,然后有效地赋值给 copy_b: Copy
.
...
copy_a = copy_b # copy_a is a Copy now!
copy_b = copy_a # assign copy_a: Copy to copy_b: Copy
reveal_type(copy_a) # Revealed type is 'aaa_testbed.Copy'
交换赋值意味着 copy_b = copy_a
发生而 copy_a
仍然是匿名类型。这会触发预期的错误:
...
copy_b = copy_a # Incompatible types in assignment (expression has type "Callable[[T], T]", variable has type "Copy")
copy_a = copy_b