[Python-Dev] Type hints -- a mediocre programmer's reaction

Steven D'Aprano steve at pearwood.info
Tue Apr 21 19:12:51 CEST 2015


On Tue, Apr 21, 2015 at 03:51:05PM +0100, Cory Benfield wrote:
> On 21 April 2015 at 15:31, Chris Angelico <rosuav at gmail.com> wrote:
> > Granted, there are some
> > vague areas - how many functions take a "file-like object", and are
> > they all the same? - but between MyPy types and the abstract base
> > types that already exist, there are plenty of ways to formalize duck
> > typing.
> 
> Are there? Can I have a link or an example, please? I feel like I
> don't know how I'm supposed to do this, and I'd like to see how that
> works. I'll even give a concrete use-case: I want to be able to take a
> file-like object that has a .read() method and a .seek() method.

I've never done this before, so I might not quite have done it 
correctly, but this appears to work just fine:

py> import abc
py> class SeekableReadable(metaclass=abc.ABCMeta):
...     @classmethod
...     def __subclasshook__(cls, C):
...         if hasattr(C, 'seek') and hasattr(C, 'read'):
...             return True
...         return NotImplemented
...
py> f = open('/tmp/foo')
py> isinstance(f, SeekableReadable)
True
py> from io import StringIO
py> issubclass(StringIO, SeekableReadable)
True
py> issubclass(int, SeekableReadable)
False


That gives you your runtime check for an object with seek() and read() 
methods. For compile-time checking, I expect you would define 
SeekableReadable as above, then make the declaration:

def read_from_start(f:SeekableReadable, size:int):
    f.seek(0)
    return f.read(size)

So now you have runtime interface checking via an ABC, plus 
documentation for the function parameter type via annotation.

But will the static checker understand that annotation? My guess is, 
probably not as it stands. According to the docs, MyPy currently 
doesn't support this sort of duck typing, but will:

    [quote]
    There are also plans to support more Python-style “duck typing” 
    in the type system. The details are still open.
    [end quote]

http://mypy.readthedocs.org/en/latest/class_basics.html#abstract-base-classes-and-multiple-inheritance


I expect that dealing with duck typing will be very high on the list 
of priorities for the future. In the meantime, for this specific use-case, 
you're probably not going to be able to statically check this type hint. 
Your choices would be:

- don't type check anything;

- don't type check the read_from_start() function, but type check 
  everything else;

- don't type check the f parameter (remove the SeekableReadable 
  annotation, or replace it with Any, but leave the size:int 
  annotation);

- possibly some type checkers will infer from the function body that f 
  must have seek() and read() methods, and you don't have to declare 
  anything (structural typing instead of nominal?);

- (a bad idea, but just for the sake of completeness) leave the 
  annotation in, and ignore false negatives.


Remember that there is no built-in Python type checker. If you have no 
checker, the annotations are just documentation and nothing else will 
have changed. If you don't like the checker you have, you'll be able to 
replace it with another.



-- 
Steve


More information about the Python-Dev mailing list