PEP 526 - var annotations and the spirit of python

Steven D'Aprano steve+comp.lang.python at pearwood.info
Fri Jul 6 02:17:28 EDT 2018


On Thu, 05 Jul 2018 16:09:52 +0200, Antoon Pardon wrote:

>> This is not an innovation of Mypy. It's how type inference is supposed
>> to work. If a particular type checker doesn't do that, it is doing it
>> wrong.
> 
> That is how type interference works in languages that have some kind of
> static typing like Haskell.

No, that's how type inference works in dynamically typed languages like 
Python as well. See Mypy for an example.

Do you have a counter-example? I'm happy to be corrected by facts, but 
not by suppositions about hypothetical type-checkers which might someday 
exist but don't yet.


> Sure if mypy want to impose something like
> that it can, but you can't interfere something like that for python
> programs in general.

Naturally -- that's why type-checking remains opt-in. Nobody, especially 
not me, says that if you see 

    x = 3

in a random Python program, that means that x must be an int everywhere 
in that program. That would be a foolish thing to say.

But if you opt-in to using a type-checker, the assumption is that you are 
writing in a less-dynamic, more-static style that will actually get some 
advantage from static type checking. If you're not doing so, then you're 
just annoying yourself and wasting time and you won't enjoy the 
experience one bit.

As many people -- including you, if I remember correctly -- have often 
pointed out, the amount of dynamism allowed in Python is a lot more than 
the amount typically used by most programs. Most of us, most of the time, 
treat variables as mostly statically typed. Reusing a variable for 
something completely unrelated is mildly frowned on, and in practice, 
most variables are only used for *one* thing during their lifetime.

Python remains a fundamentally dynamically typed language, so a static 
type checker (whether it has type inference or not) cannot cope. It 
requires gradual typing: a type system capable of dealing with mixed code 
with parts written in a static-like style and parts that remain fully 
dynamic.

Mypy makes pretty conservative decisions about which parts of your code 
to check. (E.g. it treats functions as duck-typed unless you explicitly 
annotate them.) But when it does infer types, it cannot always infer the 
type you, the programmer, intended. Often because there is insufficient 
information available:

    x = []  # we can infer that x is a list, but a list of what?
    x.append("hello world")  # allowed, or a type error?

And if the type checker turns out to make an overly-strict inference, and 
you want to overrule it, you can always annotate it as Any.

Type checking algorithms, whether static or gradual, are predicated on 
the assumption that the type of variable is consistent over the lifetime 
of that variable. (By type, I include unions, optional types, etc. "A 
float or a string" is considered a type for these purposes. So is 
"anything at all".) That's the only reasonable assumption to make for 
static analysis.

I'll grant you that a sufficiently clever type checking algorithm could 
track changes through time. Proof of concept is that we humans can do so, 
albeit imperfectly and often poorly, so it's certainly possible. But how 
we do it is by more-or-less running a simulated Python interpreter in our 
brain, tracking the types of variables as they change.

So *in principle* there could be a type-checker which does that, but as 
far as I know, there isn't such a beast. As far as I know, nobody has a 
clue how to do so with any sort of reliability, and I doubt that it is 
possible since you would surely need runtime information not available to 
a source-code static analyser.

We humans do it by focusing only on a small part of the program at once, 
and using heuristics to guess what the likely runtime information could 
be. The fact that we're not very good at it is provable by the number of 
bugs we let slip in.

So the bottom line is, any *practical* static type checker has to assume 
that a single variable is always the same type during its lifetime, and 
treat any assignment to another type as an error unless told differently.

(If you have counter-examples, I'm happy to learn better.)



By the way, you keep writing "interfere", the word is "infer":

infer
    v 1: reason by deduction; establish by deduction [syn: deduce,
         infer, deduct, derive]
    2: draw from specific cases for more general cases [syn:
       generalize, generalise, extrapolate, infer]
    3: conclude by reasoning; in logic [syn: deduce, infer]



> Unless you mean "A probable guess" by interfere.

No.


-- 
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