2

I am trying to learn about static variables in python. According to this answer this piece of code should make i unique for all the objects of class Test

The code:

>>> class Test(object):
...     _i = 3
...     @property
...     def i(self):
...             return self._i
...     @i.setter
...     def i(self,val):
...             self._i = val
... 
>>> 
>>> x1 =  Test()
>>> x1.i
3
>>> x2 = Test()
>>> x2.i
3
>>> x1.i = 10
>>> x1.i
10
>>> x2.i
3

But as you can see object x1.i is not equal to x2.i.
I tried to do this in both python 2.7 and 3.4 but the result is same. I think my understanding about this concept is wrong.

Could somebody please explain this to me or guide me to a resource.

Community
  • 1
  • 1
Nagri
  • 3,008
  • 5
  • 34
  • 63
  • 1
    They are unique as you expected in your second sentence. What exactly is your question? – Selcuk Jun 01 '16 at 08:33
  • 3
    That linked answer has it wrong. `self._i = val` will assign to a local to that instance attribute *_i* (which then shadows the class attr), not the class attribute. – Ilja Everilä Jun 01 '16 at 08:35
  • You should take a look at [this](http://stackoverflow.com/a/69067/4642859) – 3kt Jun 01 '16 at 08:36
  • @Selcuk in the linked answer it mentions that `x1.i` is equal to `x2.i`, which does not happen when I tried to do the same. my question is if I am wrong or the mentioned answer is misleading. – Nagri Jun 01 '16 at 08:41
  • @IljaEverilä That's what confused me. Thanks. – Nagri Jun 01 '16 at 08:43
  • "I am trying to learn about static variables in python" : well, Python has no such thing, period. If what you're talking about is "an attribute that is shared by all instances of the class", the correct term is "class attribute" - which is really an instance attribute of the class object (Python's classes are objects too). – bruno desthuilliers Jun 01 '16 at 09:30

2 Answers2

1

As noted, the linked answer gets it wrong.

class Test(object):
    i = 0


t = Test()
t.i = 4
print t.i
>>> 4
print t.__class__.i
>>> 0

Fields declared on the class are looked up when not found on the instance, but you cannot modify the class directly via self. self.i = 4 always modifies the instance. You can do stuff like

class Test(object):
    _i = 0

    @property
    def i(self):
        return self._i

    @i.setter
    def i(self, value):
        Test._i = value

But duplicating the class name all over the place does not seem a good idea and self.__class__ does not play too well with inheritance. This also completely hides the fact that i was initially a class variable which may or may not be a good idea, either.

Community
  • 1
  • 1
dhke
  • 15,008
  • 2
  • 39
  • 56
  • I'm not sure what you mean by "Fields declared on the class are copied to self's dictionary", but it doesn't sound right. `i` is not in the instance dict until you set it explicitly on `t`; rather, when Python resolves the name it falls back to the class-level attribute if it is not found at instance level. – Daniel Roseman Jun 01 '16 at 08:56
  • @DanielRoseman Hmm. It seems I fell for `dir()`'s magic, here (it shows `i`). Corrected. – dhke Jun 01 '16 at 09:21
0
class Test(object):

    _i = 3

    @property
    def i(self):
        return self._i

    @i.setter
    def i(self,val):
        self._i = val

if __name__ == '__main__':

    x1 =  Test()
    x2 = Test()

    x1.i = 10
    print(x1.__dict__)
    print(Test.__dict__)

{'_i': 10}
{'i': <property object at 0x02551180>, '__weakref__': <attribute '__weakref__' of 'Test' objects>, '_i': 3, '__module__': '__main__', '__doc__': None, '__dict__': <attribute '__dict__' of 'Test' objects>}

x1.i = 10 create values object

Dmitry Erohin
  • 137
  • 1
  • 5