为什么python中的显式协议不需要@runtimechecks的属性实现,而隐式协议需要



如果使用所需属性(即name(实现协议

@runtime_checkable
class DuckProtocol(Protocol):
"""Protocol for a duck"""
name: str
@abstractmethod
def quack(self):
raise NotImplementedError

如果没有name属性,则隐式子类型上isinstance的运行时检查将失败,但显式子类型不会:

class Duck1(DuckProtocol):
def quack(self):
print('quack')

class Duck2:
def quack(self):
print('quack')
class Duck3:
def __init__(self):
self.name = 'duck3'
def quack(self):
print('quack')
print(isinstance(Duck1(), DuckProtocol))
print(isinstance(Duck2(), DuckProtocol))
print(isinstance(Duck3(), DuckProtocol))

输出:

True
False
True

为什么此属性检查不扩展到显式子类型?

Duck1()不遵循DuckProtocol协议定义的规范,但它仍然是协议类的一个实例,通常意义上的对象是类的实例:它的类型是Duck1,它是DuckProtocol类的一个子类。根据isinstance的默认规则,这使Duck1()成为DuckProtocol的实例。

运行时可检查协议定义了它们自己的isinstance逻辑(通过实现__instancecheck__(,但如果该逻辑不能确定对象是协议的实例,那么它将以委托给super().__instancecheck__而不是返回False结束。在进行了一大堆间接和委派之后,我们最终进入了_abc._abc_subclasscheck,作为处理的第4步,它检查具体的子类,该检查返回True

最新更新