[Python-ideas] Proposal: Use mypy syntax for function annotations

Andrew Barnert abarnert at yahoo.com
Fri Aug 15 05:51:16 CEST 2014


On Thursday, August 14, 2014 12:03 PM, Steven D'Aprano <steve at pearwood.info> wrote:

> > On Wed, Aug 13, 2014 at 10:29:48PM +0200, Christian Heimes wrote:
> 
>>  1) I'm not keen with the naming of mypy's typing classes. The 
> visual
>>  distinction between e.g. dict() and Dict() is too small and IMHO
>>  confusing for newcomers. How about an additional 'T' prefix to make
>>  clear that the objects are referring to typing objects?
>> 
>>    from typing import TList, TDict
>> 
>>    def word_count(input: TList[str]) -> TDict[str, int]:
>>        ...
> 
> Would it be possible, and desirable, to modify the built-in types so 
> that we could re-use them in the type annotations?
> 
>     def word_count(input: list[str]) -> dict[str, int]:
> 
> 
> Since types are otherwise unlikely to be indexable like that, I think 
> that might work.

I strongly agree with the basic sentiment here, but if you take it a little bit farther, it makes things a lot simpler.


Most of the code in typing.py is a duplication of the ABCs in the collections.abc module (and io and maybe others). I understand that MyPy couldn't monkeypatch that code into the stdlib, so it had to fork the contents, but if this is going into the stdlib, can't we just modify collections/abc.py instead? Why not have the type information on collections.abc.Sequence be introspectable at runtime? More importantly, why not have the interface defined by collections.abc.Sequence be _exactly_ the same as the one checked by the static type checker, instead of just very similar?

This would also make it easier for some libraries to document their types. For example, dbm.* could inherit from or register with MutableMapping[bytes, bytes] instead of just MutableMapping, and then it wouldn't have to explain in the docstring that the keys and values have to be bytes.

Once you move the ABC typing to the actual ABCs, the only problem left is the built-in (concrete) collections. But I still don't understand why people even _want_ those to be checked. Does anyone have a good example of a function that needs to restrict its arguments to list[str] instead of Sequence[str]? Guido gave us a _terrible_ example: a function whose most obvious use was on text files, but he added a static type check that prevents it being used that way. And I think that will be the case the vast majority of the time. When I see documentation in a PyPI library or a colleague's code that says a function takes a list, it's almost always a lie; the function in fact takes any iterable (or occasionally any sequence or mutable sequence). (In fact, every exception I can think of is written in C, so it couldn't be easily annotated anyway.) It seems like we're making things a lot harder for ourselves, just for a handful of types that people are almost
 always going to use wrong.

(As a side note, generic ABCs might even be the answer to the AnyStr problem: str implements String[str], bytes implements String[bytes], bytearray implements MutableString[bytes], and classes like PyObjC's NSString can now document that they implement String[str] or String[bytes] as appropriate.)

Anyway, these leaves typing.py as nothing but functions (Union, Optional, etc.) on types defined elsewhere, in the rest of the stdlib.


More information about the Python-ideas mailing list