Defining subprotocols and subclassing protocols

You can also define subprotocols. Existing protocols can be extendedand merged using multiple inheritance. Example:

  1. # ... continuing from the previous example
  2.  
  3. class SupportsRead(Protocol):
  4. def read(self, amount: int) -> bytes: ...
  5.  
  6. class TaggedReadableResource(SupportsClose, SupportsRead, Protocol):
  7. label: str
  8.  
  9. class AdvancedResource(Resource):
  10. def __init__(self, label: str) -> None:
  11. self.label = label
  12.  
  13. def read(self, amount: int) -> bytes:
  14. # some implementation
  15. ...
  16.  
  17. resource: TaggedReadableResource
  18. 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:

  1. class NotAProtocol(SupportsClose): # This is NOT a protocol
  2. new_attr: int
  3.  
  4. class Concrete:
  5. new_attr: int = 0
  6.  
  7. def close(self) -> None:
  8. ...
  9.  
  10. # Error: nominal subtyping used by default
  11. 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.