On Mon, Mar 23, 2015 at 3:19 PM, Chris Barker <chris.barker@noaa.gov> wrote:
On Mon, Mar 23, 2015 at 2:41 PM, Cameron Simpson <cs@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)