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

Paul Moore p.f.moore at gmail.com
Wed Aug 3 11:35:56 EDT 2016


On 3 August 2016 at 16:13, Joao S. O. Bueno <jsbueno at python.org.br> wrote:
> On 3 August 2016 at 11:51, Daniel Moisset <dmoisset at machinalis.com> wrote:
>> May be I've gotten wrong my python style for many years, but I always
>> considered that the "proper" way to create instance variables was inside the
>> initializer (or in rare occasions, some other method/classmethod). For me,
>> an assignment at a class body is a class variable/constant.
>>
>> So I was going to propose "type declarations at class level are always for
>> class variables, and inside methods (preceded by "self.")  are for instance
>> variables". Using class level variables for defaults always seemed
>> unpythonic and error prone (when mutable state is involved) to me. I felt
>> that was common practice but can't find documentation to support it, so I'd
>> like to hear if I'm wrong there :)
>
> You've just missed one of the most powerful side-effects of how
> Python's class and instance variables interact:
>
> class Spaceship:
>       color = RED
>       hitpoints = 50
>
>       def powerup(self):
>
>              self.color = BLUE
>              self.hitpoints += 100
>
> Above: the defaults are good for almost all spaceship instaces - but
> when one of them is "powered up", and only them, that instance values
> are defined to be different than the defaults specified in the class.
> At that point proper instance variables are created in the instanceś
> __dict__, but for all other instances, the defaults, living in the
> instance's".__class__.__dict__" are just good enough.

Yes, but I view that as "when you ask for an instance variable, if
there isn't one you get the class variable as the default - nested
namespaces basically, just like local variables of a function and
global variables.

So to me

class Spaceship:
    hitpoints: int = 50

declares a class Spaceship, with a *class* variable hitpoints.
Instances will get that value by default, but can assign something
different.

>From a typing perspective, whether it's acceptable for an instance
variable to have a different type than the class variable with the
same name, is the point here. Because of the behaviour of acting as a
default, it probably isn't acceptable. But OTOH, there's nothing
saying you *have* to respect the link

class Whatever:
    myval : int = 20
    def __init__(self):
        self.myval = "Fooled you!"

The problem is of course that there's no way to attach a type
declaration to an instance variable, unless you allow

    self.myval : str = "Fooled you"

which opens up the possibility of declaring types for (in theory)
arbitrary expressions.

In summary, I think type annotations on variables declared at class
scope should describe the type of the class variable - because that's
what the assignment is creating. That leaves no obvious means of
declaring the type of an instance variable (can you put a
comment-style type annotation on the self.x = whatever line at the
moment?) Which is a problem, but not one (IMO) that should be solved
by somehow pretending that when you declare a class variable you're
actually declaring an instance variable.

Paul


More information about the Python-ideas mailing list