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

Steven D'Aprano steve at pearwood.info
Sun Aug 24 10:50:03 CEST 2014


On Sun, Aug 24, 2014 at 10:00:32AM +0200, Georg Brandl wrote:
> On 08/24/2014 07:54 AM, Greg Ewing wrote:
> > Steven D'Aprano wrote:
> >> I don't really understand what you're trying to say here, so I may be 
> >> misinterpreting you. I *think* that you're trying to say that for every 
> >> type in the standard library, and every class created by third parties 
> >> (including subclasses), the author will have to "declare" (in some 
> >> unknown sense) that it can be used for type annotations like MyList[T], 
> >> for some type T.
> > 
> > I suppose the run-time incarnations of the type descriptions
> > could be looser, but if you want to use them for static checking,
> > the static checker is going to have to know what MyList[T] means
> > in some detail (what effect the parameter has on the method
> > types, etc.) The programmer will have to specify all that
> > somehow.
> > 
> > The way this is done in other languages with static type
> > checking is to give the class declaration a parameter list.
> > I was envisaging that the mypy type description syntax would have
> > something equivalent. Not sure what form it would take, though.
> 
> Exactly.  Does mypy handle that?  For example, for a custom mapping
> type
> 
> class Mapping(object):
>     def setitem(self, key, value):
>         ...
> 
> how would one specify
> a) that you can use Mapping[T1, T2] as a type annotation and
> b) the type annotations for the "key" and "value" arguments?

I'm not an expert on Mypy, but I think the answer is, you can't. In 
order for Mypy to recognise your Mapping as an actual mapping, you have 
to either inherit from dict or some other mapping which Mypy knows 
about, or from typing.Generic.

http://mypy-lang.org/tutorial.html#genericclasses


from typing import typevar, Generic
T = typevar('T')
class Mapping(Generic[T, T]):
    ...


Now Mypy will know that your Mapping class should be considered a 
mapping from some type to another type, and you can use it:

def func(x:Mapping[int, str], n:int)->str:
    return x[n+1]


which will pass the static type checker.

(This is just what I understand from reading some of the docs, I welcome 
correction from anyone who knows better.)

But that's just Mypy. Another type checker might just trust you, 
regardless of what terrible lies you tell it, so long as they're 
consistent lies:

def func(x:set[int, str], n:int)->str:
    return x[n+1]


Since you've said x is a set which maps ints to strs, the code will pass 
the static check, but fail at run-time since sets don't actually support 
__getitem__. A third type checker might do structural typing instead of 
nominal typing, and be able to recognise that set doesn't have 
__getitem__ but Mapping does.

Remember that this proposal isn't about adding Mypy to the standard 
library or merging it with CPython. It remains a third-party 
implementation. People are encouraged to work on Mypy, or fork it, or 
build their own static tools, which may or may not do a better job of 
static analysis. Or runtime tools for that matter.


-- 
Steven


More information about the Python-ideas mailing list