【发布时间】:2021-10-11 03:09:55
【问题描述】:
当涉及描述符时,我观察到关于 typing.Protocol 的行为,但我并不完全理解。考虑以下代码:
import typing as t
T = t.TypeVar('T')
class MyDescriptor(t.Generic[T]):
def __set_name__(self, owner, name):
self.name = name
def __set__(self, instance, value: T):
instance.__dict__[self.name] = value
def __get__(self, instance, owner) -> T:
return instance.__dict__[self.name]
class Named(t.Protocol):
first_name: str
class Person:
first_name = MyDescriptor[str]()
age: int
def __init__(self):
self.first_name = 'John'
def greet(obj: Named):
print(f'Hello {obj.first_name}')
person = Person()
greet(person)
Person 类是否隐式实现了Named 协议? According to mypy, it isn't:
error: Argument 1 to "greet" has incompatible type "Person"; expected "Named"
note: Following member(s) of "Person" have conflicts:
note: first_name: expected "str", got "MyDescriptor[str]"
我猜这是因为 mypy 很快得出结论,str 和 MyDescriptor[str] 只是两种不同的类型。很公平。
但是,对first_name 使用普通的str 或将其包装在获取和设置str 的描述符中只是一个实现细节。这里的 Duck-typing 告诉我,我们使用 first_name(界面)的方式不会改变。
换句话说,Person 实现了Named。
作为旁注,PyCharm 的类型检查器在这种特殊情况下不会抱怨(尽管我不确定这是设计使然还是偶然)。
根据typing.Protocol的预期用途,我的理解有误吗?
【问题讨论】:
标签: python type-hinting mypy python-typing python-descriptors