[Python-ideas] ideas for type hints for variable: beyond comments

Chris Angelico rosuav at gmail.com
Tue Sep 1 18:58:49 CEST 2015


On Wed, Sep 2, 2015 at 1:01 AM, Ian <ian.team.python at gmail.com> wrote:
> Chris Angelico wrote:
> Potential problem: Function annotations are supported all the way back
> to Python 3.0, but any new syntax would be 3.6+ only. That's going to
> severely limit its value for quite some time. That doesn't mean new
> syntax can't be added (otherwise none ever would), but the bar is that
> much higher - you'll need an extremely compelling justification. "
>
> My intent must not have been clear.  I am not suggesting changing function
> annotations.  I think function annotations as they are represent an addition
> that has been well thought out and is a very useful step which extends what
> is possible in a very useful way. Pep 484 as introduced in 3.5 allows this
> to be taken further.

I understand that, but the difference here is that PEP 484 adds
meaning to something that's already been syntactically valid. If you
pull up a Python 3.1 and run this code, it will work:

def do_nothing() -> None:
    pass

The special names List and Optional and so on are not available by
default, but they're imported from typing.py anyway; it's easy enough
to make sure that typing.py works on older Pythons (maybe as a pypi
dependency).

In contrast, you're suggesting completely new syntax. That means that
any program that uses them will simply *fail to run* on any Python
older than their introduction (same as those using function
annotations can't run on Python 2). As a general rule, the bar for new
syntax is a lot higher than the bar for a new function, module, etc,
that can be implemented with existing syntax. It's certainly possible;
you just need to convince everyone that it's worth adding syntax for.

>> The other question is 'what about globals and nonlocals?'.  Currently
>> globals and nonlocals need a 'global' or 'nonlocal' statement to allow
>> assignment, but what if these values are not assigned in scope?
>
> "Not sure what you're talking about here. If they're not assigned in
> this scope, then presumably they have the same value they had from
> some other scope. You shouldn't need to declare that "len" is a
> function, inside every function that calls it. Any type hints should
> go where it's assigned, and nowhere else. "
>
> These are hints.  Not a 'need'.    The type hints may be desired in the code
> referencing the 'globals' or 'nonlocals',
> but not desired in the original context.   The idea is to allow this, NOT to
> require or need a declaration.

Okay, I think I understand you here. It's for cases like this:

# big_module.py
_cache = {}

# way further down

def function_with_annotations(thing: str) -> str
    if thing not in _cache:
        _cache[thing] = frobnicate(thing)
    return _cache[thing]

Inside this brand new function, you want to tell the type hinter that
_cache is a dict, even though you don't declare it, don't assign to
it, or anything like that. That's reasonable, but it isn't all that
common a use case; generally, if you're adding code to a module
somewhere, you can edit other places in the module to add those type
hints, or else you can simply forego the type hint for that one thing.

> Hope this helps clarify what I am trying to suggest.

Yes, thank you. I think I get what you're saying there.

>> Use of the 'local' keyword in the global namespace could indicate a value
>> not accessible in other namespaces.
>
> "I'm not sure what "not accessible" would mean. If someone imports your
> module, s/he gains access to all your globals. Do you mean that it's
> "not intended for external access" (normally notated with a single
> leading underscore)? Or is this a new feature - some way of preventing
> other modules from using these? That might be useful, but that's a
> completely separate proposal. "
>
> Good point, the single _already does what I was thinking. I never think of
> using it in this specific case. I tend to associate it with hinting that an
> identifier is for internal use within a class.  Not to get warnings about
> use from outside the global namespace of globals.

Yeah, it comes to the same thing though. I'm not sure if any linters
would pick up on "module._identifier" usages, but code reviewers
certainly could.

>> Personally I would like to go even further and allow some syntax to allow
>> (or disable) flagging the use of new variables without type hinting as
>> possible typos
>
> "If you're serious about wanting all your variables to be declared,
> then I think you want a language other than Python. There are such
> languages around (and maybe even compiling to Python byte-code, I'm
> not sure), but Python isn't built that way. Type hinting is NOT
> variable declaration, and never will be. (Though that's famous last
> words, I know, and I'm not the BDFL or even anywhere close to that. If
> someone pulls up this email in ten years and laughs in my face, so be
> it. It'd not be the first time I've been utterly confidently wrong!) "
>
> No, I am not serious about wanting all variables to be declared under normal
> circumstances.

Even under abnormal circumstances, requiring all variables to be
declared would not be Python's way. There are plenty of ways of
handling the global vs local problem. PHP says "declare all your
globals, apart from functions and magic stuff the compiler gives you
for free"; C says "declare all your locals, anything undeclared will
be searched for in progressively larger scopes - everything has to be
declared somewhere"; Python says "declare all the globals that you
assign to, anything else assigned to is local, and anything not
assigned to is searched for at run time". I don't know of *any*
language that says "declare everything", and it certainly wouldn't be
Python. Even "declare everything you assign to" would be unnecessary
overhead.

Still -1 on this proposal.

ChrisA


More information about the Python-ideas mailing list