Defining subprotocols and subclassing protocols
You can also define subprotocols. Existing protocols can be extendedand merged using multiple inheritance. Example:
- # ... continuing from the previous example
- class SupportsRead(Protocol):
- def read(self, amount: int) -> bytes: ...
- class TaggedReadableResource(SupportsClose, SupportsRead, Protocol):
- label: str
- class AdvancedResource(Resource):
- def __init__(self, label: str) -> None:
- self.label = label
- def read(self, amount: int) -> bytes:
- # some implementation
- ...
- resource: TaggedReadableResource
- resource = AdvancedResource('handle with care') # OK
Note that inheriting from an existing protocol does not automaticallyturn the subclass into a protocol – it just creates a regular(non-protocol) class or ABC that implements the given protocol (orprotocols). The Protocol
base class must always be explicitlypresent if you are defining a protocol:
- class NotAProtocol(SupportsClose): # This is NOT a protocol
- new_attr: int
- class Concrete:
- new_attr: int = 0
- def close(self) -> None:
- ...
- # Error: nominal subtyping used by default
- x: NotAProtocol = Concrete() # Error!
You can also include default implementations of methods inprotocols. If you explicitly subclass these protocols you can inheritthese default implementations. Explicitly including a protocol as abase class is also a way of documenting that your class implements aparticular protocol, and it forces mypy to verify that your classimplementation is actually compatible with the protocol.
Note
You can use Python 3.6 variable annotations (PEP 526)to declare protocol attributes. On Python 2.7 and earlier Python 3versions you can use type comments and properties.