如果使用所需属性(即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
。