[Python-Dev] Please reject or postpone PEP 526

Mark Shannon mark at hotpy.org
Fri Sep 2 09:47:00 EDT 2016


Hi everyone,

I think we should reject, or at least postpone PEP 526.

PEP 526 represents a major change to the language, however there are, I 
believe, a number of technical flaws with the PEP.

It is probable that with significant revisions it can be a worthwhile 
addition to the language, but that cannot happen in time for 3.6 beta 1 
(in 11 days).

PEP 526 claims to be an extension of PEP 484, but I don't think that is 
entirely correct.
PEP 484 was primarily about defining the semantics of pre-existing 
syntax. PEP 526 is about adding new syntax.
Historically the bar for adding new syntax has been set very high. I 
don't think that PEP 526, in its current form, reaches that bar.

Below is a list of the issues I have with the PEP as it stands.

In many cases it makes it more effort than type comments
========================================================

Type hints should be as easy to use as possible, and that means pushing 
as much work as possible onto the checker, and not burdening the programmer.

Attaching type hints to variables, rather than expressions, reduces the 
potential for inference. This makes it harder for programmer, but easier 
for the checker, which is the wrong way around.

For example,, given a function:
def spam(x: Optional[List[int]])->None: ...

With type comments, this is intuitively correct and should type check:
def eggs(cond:bool):
     if cond:
         x = None
     else:
         x = [] # type: List[int]
     spam(x)  # Here we can infer the type of x

With PEP 526 we loose the ability to infer types.
def eggs(cond:bool):
     if cond:
         x = None # Not legal due to type declaration below
     else:
        x: List[int] = []
     spam(x)

So we need to use a more complex type
def eggs(cond:bool):
     x: Optional[List[int]]
     if cond:
         x = None # Now legal
     else:
         x: = []
     spam(x)

I don't think this improves readability.
Whether this is an acceptable change is debatable, but it does need some 
debate.

It limits the use of variables
==============================

In Python a name (variable) is just a binding that refers to an object.
A name only exists in a meaningful sense once an object has been 
assigned to it. Any attempt to use that name, without an object bound to 
it, will result in a NameError.

PEP 526 makes variables more than just bindings, as any rebinding must 
conform to the given type. This looses us some of the dynamism for which 
we all love Python.

Quoting from the PEP:
```
a: int
a: str # Static type checker will warn about this.
```
In other words, it is illegal for a checker to split up the variable, 
even though it is straightforward to do so.

However, without the type declarations,
```
a = 1
a = "Hi"
```
is just fine. Useless, but fine.

We should be free to add extra variables, whenever we choose, for 
clarity. For example,
     total = foo() - bar()
should not be treated differently from:
     revenue = foo()
     tax = bar()
     total = revenue - tax

If types are inferred, there is no problem.
However, if they must be declared, then the use of meaningfully named 
variables is discouraged.

[A note about type-inference:
Type inference is not a universal panacea, but it can make life a lot 
easier for programmers in statically type languages.
Languages like C# use local type inference extensively and it means that 
many variables often do not need their type declared. We should take 
care not to limit the ability of checkers to infer values and types and 
make programmers' lives easier.
Within a function, type inference is near perfect, failing only 
occasionally for some generic types.
One place where type inference definitely breaks down is across calls, 
which is why PEP 484 is necessary.
]

It is premature
===============

There are still plenty of issues to iron out w.r.t. PEP 484 types. I 
don't think we should be adding more syntax, until we have a *precise* 
idea of what is required.

PEP 484 states:
"If type hinting proves useful in general, a syntax for typing variables 
may be provided in a future Python version."
Has it proved useful in general? I don't think it has. Maybe it will in 
future, but it hasn't yet.

It seems confused about class attributes and instance attributes
================================================================

The PEP also includes a section of how to define class attributes and 
instance attributes. It seems that everything needs to be defined in the 
class scope, even it is not an attribute of the class, but of its 
instances. This seems confusing, both to human reader and machine analyser.

Example from PEP 526:

class Starship:

     captain: str = 'Picard'
     damage: int
     stats: ClassVar[Dict[str, int]] = {}

     def __init__(self, damage: int, captain: str = None):
         self.damage = damage
         if captain:
             self.captain = captain  # Else keep the default

With type hints as they currently exist, the same code is shorter and
doesn't contaminate the class namespace with the 'damage' attribute.

class Starship:

     captain = 'Picard'
     stats = {} # type: Dict[str, int]

     def __init__(self, damage: int, captain: str = None):
         self.damage = damage # Can infer type as int
         if captain:
             self.captain = captain # Can infer type as str


This isn't an argument against adding type syntax for attributes in 
general, just that the form suggested in PEP 526 doesn't seem to follow 
Python semantics.

One could imagine applying minimal PEP 526 style hints, with standard 
Python semantics and relying on type inference, as follows:

class Starship:

     captain = 'Picard'
     stats: Dict[str, int] = {}

     def __init__(self, damage: int, captain: str = None):
         self.damage = damage
         if captain:
             self.captain = captain

The PEP overstates the existing use of static typing in Python
==============================================================

Finally, in the rejected proposal section, under "Should we introduce 
variable annotations at all?" it states that "Variable annotations have 
already been around for almost two years in the form of type comments, 
sanctioned by PEP 484."
I don't think that this is entirely true.
PEP 484 was about the syntax for types, declaring parameter and return 
types, and declaring custom types to be generic.
PEP 484 does include a description of type comments, but they are always 
annotations on assignment statements and were primarily intended for use 
in stub files.



Please don't turn Python into some sort of inferior Java.
There is potential in this PEP, but in its current form I think it 
should be rejected.

Cheers,
Mark.




More information about the Python-Dev mailing list