PEP 526 - var annotations and the spirit of python

Steven D'Aprano steve+comp.lang.python at
Wed Jul 4 22:01:01 EDT 2018

On Wed, 04 Jul 2018 19:57:12 +0100, Bart wrote:

> On 04/07/2018 16:31, Steven D'Aprano wrote:
>> On Wed, 04 Jul 2018 13:48:26 +0100, Bart wrote:
>> Of course the type (whether inferred or annotated) applies for the
>> entire scope of that variable.
> In that case I don't understand what you're complaining about. You say
> that hinting is not needed here:
>    x = 3
> because you know x will be int at this point. But what you don't know if
> whether x will keep its int type.

*I* don't know, but that's why I'm running a type-checker.

*The checker* knows, because it does static analysis of the code looking 
for mismatches between types (say, trying to add None to an int, or 
multiply a string by a dict, or assigning a list to something that ought 
to be a float).

>> With type-inference, the type-checker is smart enough to recognise what
>> type a variable is supposed to be (at least sometimes):
>>      x = 3;  # of course it's an int, what else could it be? x = f(x);
>> and likewise complain if f(x) returns something other than an int.
> Are you still talking about Python here? Python is famous for being
> highly dynamic. So that that second assignment could set x to ANYTHING.

Of course it could. And if that's your intention, as author of the code, 
you can simply *not run the type checker*, and the code will run just as 
you've written it.

But we know (as so many people keep reminding us) that just because 
Python is extremely dynamic, that doesn't necessarily mean that we use it 
in extremely dynamic ways. Most of the time, say, 95% of the time, if x 
is an int *here*, it is intended to *stay* an int all the way through the 
lifetime of that variable.

In those cases, if a later assignment to x sets it to "anything", that 
means you have a bug in your code. It might not be an obvious bug, or one 
that you spot up front. Testing can only prove the presence of bugs, not 
their absence.

So you'll probably get a bunch of TypeErrors, one at a time, and over a 
period of many days or months or years, gradually your users will find 
each TypeError in your code, and report the bug, and you'll fix it.

If that works for you, great!

Or... you can run the type-checker, it will perform static analysis of 
your code, using whatever type information it can infer or you have 
annotated, and spot some (if not all) of those type errors ahead of time, 
so you can fix them immediately.

If that doesn't work for you, that's cool too. That's why these are 
optional type hints not mandatory type declarations.

> I though the point of the type hint was to say that x has a particular
> type and it always keeps that same type. That way it is possible to make
> some assumptions about it.


> Otherwise, what's the point?

There wouldn't be one.

> I understand that type hinting doesn't enforce anything, such as
> checking that anything assigned to x is actually an int. Although that
> wouldn't be hard to do: just implement every x = y as x = int(y) or
> better, x = intcheck(y).

No, that would needlessly slow down the runtime. First off, it would be 

    x = int(2)

is just a waste of a function call. Secondly, it would be *wrong*:

    x = f(x)

is supposed to return an int, but is buggy and return a string, which by 
some ill chance happens to be "12345" which int() will happily convert.

And thirdly, failures will still be *runtime failures*, just as they 
already are. So even when you catch the error, you aren't catching them 
ahead of time.

Python already does runtime type checking. Every time you get a TypeError 
or AttributeError, that's a form of runtime type checking. The point of 
static type checking is to do some of the work ahead of time, and detect 
type errors before you run the code.

Steven D'Aprano
"Ever since I learned about confirmation bias, I've been seeing
it everywhere." -- Jon Ronson

More information about the Python-list mailing list