[Python-ideas] Type Hinting Kick-off

Guido van Rossum guido at python.org
Mon Dec 22 08:02:00 CET 2014

On Sun, Dec 21, 2014 at 9:35 PM, Nick Coghlan <ncoghlan at gmail.com> wrote:
> [...] I realised in trying to write this email that I don't currently
> understand the consequences of not having annotation data available for a
> module in terms of the ripple effects that may have on what scanners can
> check - from the end user perspective, I believe that's something I'd need
> to know, even though I wouldn't necessarily need to know *why* those were
> the default assumptions for unannotated operations. (I'm curious about the
> latter from a language *design* perspective, but I think I'd be able to use
> the feature effectively just by knowing the practical consequences without
> necessarily understanding the theory)

That's what "Any" is for. If an object's type is "Any", then every
operation on it (including getattr) also return "Any", from the checker's
POV. You stop the ripples with an explicitly declared type -- e.g. if you
pass it to a function as an arg with a type annotation, inside that
function the argument is assumed to have the declared type (but the "Any"
prevents diagnostics about the call site). In mypy there is also an
explicit cast operator (http://mypy.readthedocs.org/en/latest/casts.html),
we may add this to the PEP (it's one of the many details left out from the
Quip doc that need to be filled in for the actual PEP).

The importance of "Any" cannot be overstated -- without it, you either have
to declare types everywhere, or you end up with a "everything inherits from
everything" situation. The invention of "Any" prevents this (and this is
why is-consistent-with cannot be transitive). Read Jeremy Siek's Gradual
Typing blog post for more.

Also, consider the important difference between Any and object. They are
both at the top of the class tree -- but object has *no* operations (well,
almost none -- it has repr() and a few others), while Any supports *all*
operations (in the sense of "is allowed by the type system/checker"). This
places Any also at the *bottom* of the class tree, if you can call it that.
(And hence it is more a graph than a tree -- but if you remove Any, what's
left is a tree again.)

Any's "contagiousness" is somewhat similar to NaN for floats, but it has
its limits -- e.g. repr() of Any is still a string, and Any==Any is still a
bool. Another similar concept exists IIUC in Objective-C, which has a kind
of null object that can be called (sent a message), always returning
another null result. (This has occasionally been proposed for Python's
None, but I don't think it is appropriate.) But of course, Any only exists
in the mind of the static checker -- at runtime, the object has a concrete
type. "Any" is just the type checker's way to say "I don't know the type,
and I don't care". I bet compilers with good error recovery have some
similar concept internally, used to avoid a cascade of errors due to a
single typo.

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

More information about the Python-ideas mailing list