PEP 0526 next round of edits (#72)

* setting up pep-0526 headers

* Some work on PEP 526 abstract and rationale

* adding info about annotations specs

* PEP 526 updates

* PEP 526 updates

* adding section about instance variables inside methods

* Change declare/declaration -> annotate/annotation.

* Add notice for reviewers.
This commit is contained in:
Guido van Rossum 2016-08-15 16:25:09 -07:00 committed by GitHub
parent 82fbafb118
commit b9e9bee341
1 changed files with 169 additions and 5 deletions

View File

@ -1,5 +1,5 @@
PEP: 526
Title: Variable Declaration Syntax
Title: Syntax for Variable and Attribute Annotations
Version: $Revision$
Last-Modified: $Date$
Author: Ryan Gonzalez <rymg19@gmail.com>, Philip House <phouse512@gmail.com>, Guido van Rossum <guido@python.org>
@ -9,6 +9,16 @@ Content-Type: text/x-rst
Created: 09-Aug-2016
Python-Version: 3.6
Notice for Reviewers
====================
This PEP is not ready for review. We're merely committing changes
frequently so we don't end up with a huge merge conflict. For minor
textual nits please use https://github.com/python/peps/pull/72. For
discussion about contents, please refer to
https://github.com/python/typing/issues/258 (but please be patient, we
know we're way behind addressing all comments).
Abstract
========
@ -22,7 +32,7 @@ type comments::
class Cls:
my_class_attr = True # type: bool
This PEP aims at adding syntax to Python for declaring the types of variables and
This PEP aims at adding syntax to Python for annotating the types of variables and
attributes, instead of expressing them through comments::
a: List[int] = []
@ -36,10 +46,10 @@ Rationale
Although type comments work well, the fact that they're expressed through
comments has some downsides:
- Text editors often highlight comments differently from type declarations.
- There isn't a way to declare the type of an undefined variable; you need to
- Text editors often highlight comments differently from type annotations.
- There isn't a way to annotate the type of an undefined variable; you need to
initialize it to ``None`` (e.g. ``a = None # type: int``).
- Variables declared in a conditional branch are difficult to read::
- Variables annotated in a conditional branch are difficult to read::
if some_value:
my_var = function() # type: Logger
@ -55,3 +65,157 @@ comments has some downsides:
The majority of these issues can be alleviated by making the syntax a core part of
the language.
Specification
=============
*** big key concepts, not quite sure what the best way to organize this would be,
or if they deserve their own sections ***
Normal Variable Typing
**********************
The types of locals and globals can be annotated as follows::
some_number: int # variable without default
some_list: List[int] = [] # variable with default
Being able to omit the initial value allows for easier typing of variables
assigned in conditional branches::
sane_world: bool
if 2+2 == 4:
sane_world = True
else:
sane_world = False
Note that, although this syntax does allow tuple packing, it does *not* allow one
to annotate the types of variables when tuple unpacking is used::
# Tuple packing with variable annotation syntax
t: Any = (1, 2, 3)
# Tuple unpacking with type comments
x, y, z = t # type: int, int, int
# Tuple unpacking with variable annotation syntax
x: int
y: int
z: int
x, y, z = t
Omitting a default value leaves the variable uninitialized::
a: int
print(a) # raises NameError
However, annotating a local variable will cause the interpreter to always make
it a local::
def f():
a: int
print(a) # raises UnboundLocalError
# Commenting out the `a: int` makes it a NameError!
as if the code were::
def f():
if False: a = 0
print(a) # raises UnboundLocalError
Class Variable Typing
*********************
Adding variable types allow for us annotate the types of instance variables in class
bodies. In particular, the value-less notation (`a: int`) allows us to annotate
instance variables that should be initialized in `__init__` or `__new__`. The
proposed syntax looks as follows::
class Starship:
captain: str # instance variable without default
damage: int = 0 # instance variable with default
stats: class Dict[str, int] = {} # class variable with initialization
Duplicate annotations
*********************
Any duplicate type annotations will be ignored::
a: int
a: int # Doesn't do anything.
The Python compiler will not validate the type expression, and leave it to
the type checker to complain. The above code will be allowed by the
compiler at runtime.
Where annotations aren't allowed
********************************
It's illegal to attempt to annotate ``global`` and ``nonlocal``::
def f():
global x: int # SyntaxError
The reason is that ``global`` and ``nonlocal`` don't own variables;
therefore, the type annotations belong in the scope owning the variable.
In addition, you cannot annotate variable used in a ``for`` or ``with``
statement; they must be annotated ahead of time, in a similar manner to tuple
unpacking::
a: int
for a in my_iter:
f: MyFile
with myfunc() as f:
# ...
Capturing Types at Runtime
**************************
In order to capture variable types that are usable at runtime, we store the
types in `__annotations__` as dictionaries at various levels. At each level (for
example, global), the types dictionary would be stored in the `__annotations__`
dictionary for that given level. Here is an example for both global and class
level types::
# print global type annotations
players: Dict[str, Player]
print(__annotations__)
# print class type annotations
class Starship:
hitpoints: class int = 50
stats: class Dict[str, int] = {}
shield: int = 100
captain: str # no initial value
print(Starship.__annotations__)
A note about locals -- the value of having annotations available locally does not
offset the cost of having to create and populate the annotations dictionary on
every function call.
These annotations would be printed out from the previous program as follows::
{'players': Dict[str, Player]}
{'hitpoints': ClassVar[int],
'stats': ClassVar[Dict[str, int]],
'shield': int,
'captain': str
}
Mypy supports allowing `# type` on assignments to instance variables and other things.
In case you prefer annotating instance variables in `__init__` or `__new__`, you can
also annotate variable types for instance variables in methods. Despite this,
`__annotations__` will not be updated for that class.
Backwards Compatibility
=======================
Copyright
=========
This document has been placed in the public domain.