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

Gregory P. Smith greg at krypto.org
Tue Aug 2 21:15:46 EDT 2016


On Mon, Aug 1, 2016 at 10:14 PM Guido van Rossum <guido at python.org> wrote:

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

First reaction.  It doesn't actually seem too bad now.  It is already legal
to just say `a` as a statement so this isn't much different.

def f():
  a

is already legal.  So `a: List[float]` would at least be meaningful rather
than a meaningless statement that any linter should question. :)


>
> 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.
>

I agree, cdef is their own mess. :)


>
> 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.
>

-gps


> 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)
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20160803/a62bf533/attachment-0001.html>


More information about the Python-ideas mailing list