[Python-ideas] PEP 484 (Type Hints) -- first draft round
Guido van Rossum
guido at python.org
Sun Jan 18 04:51:15 CET 2015
On Fri, Jan 16, 2015 at 9:49 PM, Steven D'Aprano <steve at pearwood.info>
> On Fri, Jan 16, 2015 at 09:17:36AM -0800, Guido van Rossum wrote:
> > Type Definition Syntax
> > ======================
> > An optional type is also automatically assumed when the default value is
> > ``None``, for example::
> > def handle_employee(e: Employee = None): ...
> > This is equivalent to::
> > def handle_employee(e: Optional[Employee] = None): ...
> > .. FIXME: Is this really a good idea?
> I think it is. It seems to me to be a form of type inference: you are
> declaring that e is an Employee, but inferring that it could also be
> None. Either the type system reports this as an error, or it infers that
> the type is intended to be optional. Given how common it is for
> arguments to be "X or None" having shorthand for that is a good thing.
Agreed. I'm removing the FIXME.
> > Platform-specific type checking
> > -------------------------------
> > In some cases the typing information will depend on the platform that
> > the program is being executed on. To enable specifying those
> > differences, simple conditionals can be used::
> Since CPython isn't going to do type-checking itself, instead it
> will leave it up to external tools. Given that, I
> assume that you are specifying the minimum requirements for such a
> tool, rather than a declaration of what some specific tool will do.
Yes. A type checker is an immensely complex tool, and there are many gray
areas where the PEP just can't hope to be rigorous. In the end the use of
the type checker is meant as a linter, not as the rigorous definition of
the language (which can do things no type checker can understand).
> Hence, type-checkers should be able to deal with "simple conditionals"
> as in the examples given, and are not required to emulate a full Python
> interpreter in order to make sense of arbitrarily complex conditionals
> if (PY2 and WINDOWS) or (PY3 and POSIX): ...
That already feels too complex -- not because the checker couldn't figure
out the value, but because I don't want to support complex expressions in
other places (before you know it, you're using conditionals in argument
annotations, and I really don't want to go there).
> But a sophisticated type-checker may offer more than the minimum.
> Is this correct?
> There are a number of places where the PEP mentions "the type checker",
> e.g. the next paragraph. I think the PEP should clarify what exactly is
> meant by that.
You're right. There's some language in the "Usage Patterns" sections but it
makes more sense to explain this upfront. (Also that section hints at
runtime checking, which really should be considered quite out of scope.)
> > Arbitrary literals defined in the form of ``NAME = True`` will also be
> > accepted by the type checker to differentiate type resolution::
> As above. How arbitrary are the literals? Only bool flags? If so, the
> PEP should say "Boolean literals" rather than "arbitrary literals".
Agreed. I think we need to work with Jukka on a spec of what the minimum
complexity is that the checker should support for this purpose (even though
in other contexts it of course must understand non-constant expressions,
since it must type-check them :-).
> > Compatibility with other uses of function annotations
> > -----------------------------------------------------
> > A number of existing or potential use cases for function annotations
> > exist, which are incompatible with type hinting. These may confuse a
> > static type checker. However, since type hinting annotations have no
> > run time behavior (other than evaluation of the annotation expression
> > and storing annotations in the ``__annotations__`` attribute of the
> > function object), this does not make the program incorrect -- it just
> > makes it issue warnings when a static analyzer is used.
> I understood from early discussions that type checking would only be
> enabled if you imported `typing`. If so, then the easy way to disable
> type checks for a whole module was not to import anything from `typing`.
I changed my mind about that (and I don't think mypy has ever strictly
followed this rule). The reason is that it's quite sensible to use built-in
types (e.g. int) and user-defined classes as type annotations and expect
the checker to do its thing. It's only when you need things like generic
classes, unions etc. that you must import typing.
> > To mark portions of the program that should not be covered by type
> > hinting, use the following:
> > * a ``@no_type_checks`` decorator on classes and functions
> > * a ``# type: ignore`` comment on arbitrary lines
> > .. FIXME: should we have a module-wide comment as well?
> Rather than have to comment each and every line, can we marking entire
> sections with a directive?
> # type: off
> # type: on
> This will still allow `type: ignore` if you want to skip a single line,
> and allow module-wide control by simply starting your module with
> `type: off` and not turning it back on.
We don't have the definitive design. See
> Where will the @no_type_checks decorator live? In the typing module or
> as a builtin?
In the typing module.
> I see from below that directives of the form `type: spam` are allowed.
> That could clash with `type: ignore` etc. Although it is not PEP 8
> compliant, people might have classes called "ignore", "on", "off". How
> about we require keywords to the type directive to have a leading +
> # type: +ignore # Keyword "ignore", don't type check this line.
> # type: ignore # Declare the type is class "ignore".
I'm not keen on the special meaning of +. We might using "# typing: ..."
for directives, or we might just use some all_caps names, e.g. "# type:
> Otherwise there is going to be the risk of clashes.
I think the risk of clashes can be made sufficiently low that we can say
> > Type Hints on Local and Global Variables
> > ========================================
> > No first-class syntax support for explicitly marking variables as being
> > of a specific type is added by this PEP. To help with type inference in
> > complex cases, a comment of the following format may be used::
> > x =  # type: List[Employee]
> Without the type declaration, x would be inferred to be of type
> List[Any]. Is that correct? Perhaps that should go into the PEP.
Correct. (What else could it be? Although I think that if x has been given
a type earlier, the  is checked against that type.)
If you think the PEP is insufficiently clear, could you submit a PR? (BTW,
to anyone else considering PRs against the GitHub repo, please create a
regular issue when you want to change the proposed behavior or syntax. PRs
are good for clarifications, typos etc.)
> > In the case where type information for a local variable is needed before
> > if was declared, an ``Undefined`` placeholder might be used::
> Typo, should read "it was declared".
Will fix. (I also think it should be "it is declared".)
--Guido van Rossum (python.org/~guido)
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the Python-ideas