微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

回调协议 - 我们什么时候需要双下划线前缀?

如何解决回调协议 - 我们什么时候需要双下划线前缀?

mypy docs 阅读

可以使用回调协议和:py:data:~typing.Callable 类型 可互换。 :py:meth:__call__ <object.__call__> 方法中的关键字参数名称必须相同,除非是 double 使用下划线前缀。例如:

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。