为什么 python 中的显式协议不需要 @runtimechecks 的属性实现,但隐式协议需要?
Why do explicit protocols in python not require attribute implementation for @runtimechecks, but implicit protocols do?
如果协议是用必需的属性实现的,即 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
协议定义的规范,但它仍然是协议 class 的实例,通常意义上的对象是 classes:它的类型是 Duck1
,它是 DuckProtocol
class 的子 class。根据 isinstance
的默认规则,这使得 Duck1()
成为 DuckProtocol
.
的实例
运行时可检查协议定义了它们自己的 isinstance
逻辑(通过实施 __instancecheck__
), but if that logic doesn't decide the object is an instance of the protocol, it ends by delegating to super().__instancecheck__
instead of returning False
. After a whole bunch more indirection and delegation, we eventually end up in _abc._abc_subclasscheck
, which checks for concrete subclasses 作为其处理的第 4 步,并且此检查 returns True
.
如果协议是用必需的属性实现的,即 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
协议定义的规范,但它仍然是协议 class 的实例,通常意义上的对象是 classes:它的类型是 Duck1
,它是 DuckProtocol
class 的子 class。根据 isinstance
的默认规则,这使得 Duck1()
成为 DuckProtocol
.
运行时可检查协议定义了它们自己的 isinstance
逻辑(通过实施 __instancecheck__
), but if that logic doesn't decide the object is an instance of the protocol, it ends by delegating to super().__instancecheck__
instead of returning False
. After a whole bunch more indirection and delegation, we eventually end up in _abc._abc_subclasscheck
, which checks for concrete subclasses 作为其处理的第 4 步,并且此检查 returns True
.