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

Guido van Rossum guido at python.org
Tue Aug 2 01:14:30 EDT 2016


What makes you respond so vehemently to `a: float`?

The `def` keyword has been proposed before, but *I* have a vehement
response to it; `def` is for functions.

The Cython syntax may live forever in Cython, but I don't want to add
it to Python, especially since we already have function annotations
using `var: type = default` -- variable declarations must somehow
rhyme with this.

The `local` keyword isn't horrible but would still require a
`__future__` import and a long wait, which is why I'm exploring just
`var: type = value`. I think we can pull it off syntactically, using a
trick no more horrible than the one we already employ to restrict the
LHS of an assignment even though the grammar seen by the parser is
something like `expr_stmt: testlist ('=' testlist)*` (at least it was
something like this long ago -- it's more complex now but the same
idea still applies, since the official parser is still LR(1)).

Regarding scopes, I like the way mypy currently does this -- you can
only have a `# type` comment on the first assignment of a variable,
and scopes are flat as they are in Python. (Mypy is really
anticipating a syntax for variable declarations here.) Seems we agree
on this, at least.

On Mon, Aug 1, 2016 at 4:39 PM, Gregory P. Smith <greg at krypto.org> wrote:
>
> On Mon, Aug 1, 2016 at 2:32 PM Guido van Rossum <guido at python.org> wrote:
>>
>> PEP 484 doesn't change Python's syntax. Therefore it has no good
>> syntax to offer for declaring the type of variables, and instead you
>> have to write e.g.
>>
>> a = 0  # type: float
>> b = []  # type: List[int]
>> c = None  # type: Optional[str]
>>
>> I'd like to address this in the future, and I think the most elegant
>> syntax would be to let you write these as follows:
>>
>> a: float = 0
>> b: List[int] = []
>> c: Optional[str] = None
>>
>> (I've considered a 'var' keyword in the past, but there just are too
>> many variables named 'var' in my code. :-)
>>
>
> My first impression of this given the trivial int and str examples is... Why
> are you declaring types for things that are plainly obvious?  I guess that's
> a way of saying pick better examples. :)  Ones where the types aren't
> implied by obvious literals on the RHS.
>
> Your examples using complex types such as List[int] and Optional[str] are
> already good ones as that can't be immediately inferred.
>
> b: str = module.something(a)
>
> is a better example as without knowledge of module.something we cannot
> immediately infer the type and thus the type declaration might be considered
> useful to prevent bugs rather than annoying read and keep up to date.
>
> I predict it will be more useful for people to declare abstract
> interface-like types rather than concrete ones such as int or str anyways.
> (duck typing ftw)  But my predictions shouldn't be taken too seriously.  I
> want to see what happens.
>
>>
>> There are some corner cases to consider. First, to declare a
>> variable's type without giving it an initial value, we can write this:
>>
>> a: float
>
>
> I don't like this at all.  We only allow pre-declaration without an
> assignment using keywords today.  the 'local' suggestion others have
> mentioned is worth consideration but I worry any time we add a keyword as
> that breaks a lot of existing code.  Cython uses 'cdef' for this but we
> obviously don't want that as it implies much more and isn't obvious outside
> of the cython context.
>
> You could potentially reuse the 'def' keyword for this.
>
> def a: List[float].
>
> This would be a surprising new syntax for many who are used to searching
> code for r'^\s*def' to find function definitions.  Precedent: Cython already
> overloads its own 'cdef' concept for both variable and function/method use.
>
> Potential alternative to the above def (ab)use:
>
> def a -> List[float]
> def a List[float]
> def List[float] a  # copies the Cython ordering which seems to derive from C
> syntax for obvious reasons
>
> But the -> token really implies return value while the : token already
> implies variable type annotation.  At first glance I'm not happy with these
> but arguments could be made.
>
>> Second, when these occur in a class body, they can define either class
>> variables or instance variables. Do we need to be able to specify
>> which?
>>
>> Third, there's an annoying thing with tuples/commas here. On the one
>> hand, in a function declaration, we may see (a: int = 0, b: str = '').
>> On the other hand, in an assignment, we may see
>>
>> a, b = 0, ''
>>
>> Suppose we wanted to add types to the latter. Would we write this as
>>
>> a, b: int, str = 0, ''
>>
>> or as
>>
>> a: int, b: str = 0, ''
>>
>> ??? Personally I think neither is acceptable, and we should just write it
>> as
>>
>> a: int = 0
>> b: str = ''
>
>
> Disallowing ": type" syntax in the presence of tuple assignment seems simple
> and wise to me. Easy to parse. But I understand if people disagree and want
> a defined way to do it.
>
>> but this is a slight step back from
>>
>> a, b = 0, ''   # type: (int, str)
>>
>> --
>> --Guido van Rossum (python.org/~guido)
>
>
> When thinking about how to spell this out in a PEP, it is worth taking into
> account existing ways of declaring types on variables in Python. Cython took
> the "Keyword Type Name" approach with "cdef double j" syntax.
> http://cython.readthedocs.io/en/latest/src/quickstart/cythonize.html
>
> Is it an error to write the following (poor style) code declaring a type for
> the same variable multiple times:
>
> c: int = module.count_things(x)
> compute_thing(c)
> if c > 3:
>   c: str = module.get_thing(3)
>   logging.info('end of thing 3: %s', c[-5:])
> do_something(c)
>
> where c takes on multiple types within a single scope? static single
> assignment form would generate a c', c'', and union of c' and c'' types for
> the final do_something call to reason about that code.  but it is entirely
> doable in Python and does happen in unfortunately real world messy code as
> variables are reused in bad ways.
>
> My preference would be to make it an error for more than one type to be
> declared for the same variable.
> First type ever mentioned within the scope wins and all others are
> SyntaxError worthy.
> Assigning to a variable in a scope before an assignment that declares its
> type should probably also be a SyntaxError.
>
> -gps
>



-- 
--Guido van Rossum (python.org/~guido)


More information about the Python-ideas mailing list