If a protocol is implemented with a required attribute i.e. name
@runtime_checkable
class DuckProtocol(Protocol):
"""Protocol for a duck"""
name: str
@abstractmethod
def quack(self):
raise NotImplementedError
a runtime check of isinstance on an implicit subtype will fail if there is no name attribute, but an explicit one will not:
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))
Output:
True
False
True
Why does this attribute check not extend to explicit subtypes?