[Python-Dev] PEP 544: Protocols

Brett Cannon brett at python.org
Mon Mar 20 14:07:32 EDT 2017


I'm overall very supportive of seeing something like this make it into
Python to further strengthen duck typing in the language. I know I've
wanted something something like this since ABCs were introduced.

I personally only have one issue/clarification for the PEP.

On Mon, 20 Mar 2017 at 05:02 Ivan Levkivskyi <levkivskyi at gmail.com> wrote:

> [SNIP]
> Protocol members
> ----------------
>
> All methods defined in the protocol class body are protocol members, both
> normal and decorated with ``@abstractmethod``. If some or all parameters of
> protocol method are not annotated, then their types are assumed to be
> ``Any``
> (see PEP 484). Bodies of protocol methods are type checked, except for
> methods
> decorated with ``@abstractmethod`` with trivial bodies. A trivial body can
> contain a docstring.
>

What is a "trivial body"? I don't know of any such definition anywhere in
Python so this is too loosely defined. You also don't say what happens if
the body isn't trivial. Are tools expected to raise an error?


> Example::
>
>   from typing import Protocol
>   from abc import abstractmethod
>
>   class Example(Protocol):
>       def first(self) -> int:     # This is a protocol member
>           return 42
>
>       @abstractmethod
>       def second(self) -> int:    # Method without a default implementation
>           """Some method."""
>
> Note that although formally the implicit return type of a method with
> a trivial body is ``None``,
>

This seems to suggest a trivial body is anything lacking a return statement.


> type checker will not warn about above example,
> such convention is similar to how methods are defined in stub files.
> Static methods, class methods, and properties are equally allowed
> in protocols.
>

Personally, I think even an abstract method should be properly typed. So in
the example above, second() should either return a reasonable default value
or raise NotImplementedError. My argument is "explicit is better than
implicit" and you make errors when people call super() on an abstract
method that doesn't return None when it doesn't make sense.

I would also argue that you can't expect an abstract method to always be
simple. For instance, I might define an abstract method that has horrible
complexity characteristics (e.g. O(n**2)), but which might be acceptable in
select cases. By making the method abstract you force subclasses to
explicitly opt-in to using the potentially horrible implementation.

-Brett


>
> To define a protocol variable, one must use PEP 526 variable
> annotations in the class body. Additional attributes *only* defined in
> the body of a method by assignment via ``self`` are not allowed. The
> rationale
> for this is that the protocol class implementation is often not shared by
> subtypes, so the interface should not depend on the default implementation.
> Examples::
>
>   from typing import Protocol, List
>
>   class Template(Protocol):
>       name: str        # This is a protocol member
>       value: int = 0   # This one too (with default)
>
>       def method(self) -> None:
>           self.temp: List[int] = [] # Error in type checker
>
> To distinguish between protocol class variables and protocol instance
> variables, the special ``ClassVar`` annotation should be used as specified
> by PEP 526.
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20170320/526668a5/attachment.html>


More information about the Python-Dev mailing list