[Python-ideas] PEP 484 (Type Hints) -- second draft

Guido van Rossum guido at python.org
Mon Mar 23 23:35:23 CET 2015


On Mon, Mar 23, 2015 at 3:19 PM, Chris Barker <chris.barker at noaa.gov> wrote:

>
> On Mon, Mar 23, 2015 at 2:41 PM, Cameron Simpson <cs at zip.com.au> wrote:
>
>> But it scales very badly; what of a 4 way if etc? It moves from a bit
>> less readable to a nightmare.
>>
>
> in python one particular type or None is a very common idiom -- well worth
> special casing. Somethign that could take or return 4 different types is a
> far less usual case, we can be more verbose there.
>
> Note that Cython and Pyrex default to "or NOne", and you have to do
>
> func( int x not None)
>
> if you don't want to allow the None. That's because None as a not-set-yet
> value is so common. In this case, it's a mistake to make it the default, as
> Cython does not generate checks later for None, so it can get ugly if you
> don't specifically test for it in your code. None the less, it's very
> useful.
>

There's a lot of discussion in the typehinting tracker and also in the mypy
tracker about what to do with "or None" types. mypy currently doesn't
complain about this because it's deemed too noisy (Jukka regularly tries to
convert various real-world code bases to type hints, and he learns a lot
from these).

That said, about the specific example used here, the best way to deal with
this currently is to put an annotation comment on the first line, like this:

    if a < 0:
        r = None  # type: Optional[float]
    else:
        r = sqrt(a)

There's currently one place in the PEP where Optional[t] is automatically
inferred: an argument that's annotated and has None for a default:

def foo(x: int = None):
    ...

The actual type of x here is Optional[int].

Note that the PEP doesn't prescribe that the type of a variable becomes the
union of the type assigned to in in separate branches of a conditional.
This is intentional -- except for a few special cases (like discussed here)
giving a variable a different type in different branches (if it is used
after the branches join) is more likely a bug than desired.

Experimenting with this in mypy is difficult because it explicitly silences
complaints about None (see above); if you want to understand what it does
in general it's better to experiment with two distinct non-None types, e.g.
float and str. Using this approach I found that when you use an
if-statement, you should put a #type: comment on the assignment in the
first branch to silence it; when you use an if-expression, there's no way
to shut it up! (This is exactly the opposite of the assumption that was
made earlier in this thread.)

PS. About the cast() argument order, I've opened a tracker issue for this:
https://github.com/ambv/typehinting/issues/63

-- 
--Guido van Rossum (python.org/~guido)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20150323/05a75e8c/attachment-0001.html>


More information about the Python-ideas mailing list