[Python-ideas] Trial balloon: adding variable type declarations in support of PEP 484

Nick Coghlan ncoghlan at gmail.com
Thu Aug 4 08:37:33 EDT 2016


On 4 August 2016 at 02:11, Guido van Rossum <guido at python.org> wrote:
> On Wed, Aug 3, 2016 at 8:24 AM, Nick Coghlan <ncoghlan at gmail.com> wrote:
>> On 3 August 2016 at 10:48, Alvaro Caceres via Python-ideas
>> <python-ideas at python.org> wrote:
>>> The criticism I would make about allowing variables without assignments like
>>>
>>>   a: float
>>>
>>> is that it makes my mental model of a variable a little bit more complicated
>>> than it is currently. If I see "a" again a few lines below, it can either be
>>> pointing to some object or be un-initialized. Maybe the benefits are worth
>>> it, but I don't really see it, and I wanted to point out this "cost".
>>
>> This concern rings true for me as well - "I'm going to be defining a
>> variable named 'a' later and it will be a float" isn't a concept
>> Python has had before. I *have* that concept in my mental model of
>> C/C++, but trying to activate for Python has my brain going "Wut?
>> No.".
>
> Have you annotated a large code base yet? This half of the proposal
> comes from over six months of experience annotating large amounts of
> code (Dropbox code and mypy itself). We commonly see situations where
> a variable is assigned on each branch of an if/elif/etc. structure. If
> you need to annotate that variable, mypy currently requires that you
> put the annotation on the first assignment to the variable, which is
> in the first branch. It would be much cleaner if you could declare the
> variable before the first `if`. But picking a good initializer is
> tricky, especially if you have a type that does not include None.

Ah, that makes sense - given that motivation, I agree it's worth
introducing the concept.

You'll probably want to make sure to give that example from the mypy
code (or a simpler version), as I expect that pre-declaration aspect
will be the most controversial part of the whole proposal.

I wonder if there's some way we could make that new statement form
trigger the following runtime behaviour:

    a : int
    a # This raises a new UnboundNameError at module scope,
UnboundLocalError otherwise

Otherwise we're at risk of allowing thoroughly confusing runtime behaviour like:

    >>> a = "Not an int"
    >>> def f():
    ...     # a: int would go here
    ...     print(a) # This should really fail
    ...
    >>> f()
    Not an int

The possibility that springs to mind is a new dedicated opcode,
DECLARE_NAME, that works like an assignment that appears anywhere in
the function for function namespaces, and does something new for
module and class namespaces where it's like an assignment, but doesn't
appear in locals(). Depending on how the latter work, we may even be
able to raise a new UnboundAttributeError subclass for attempts to
access declared-but-not-defined attributes.

We'd also want the new syntax to conflict with both global and
nonlocal, the same way they currently conflict with each other:

>>> def f():
...    global a
...    nonlocal a
...
  File "<stdin>", line 2
SyntaxError: name 'a' is nonlocal and global

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia


More information about the Python-ideas mailing list