3

I have created class Circle with no instance variables. I've added a class-method from_diameter to generate the circle with given diameter.

class Circle:

    @classmethod
    def from_diameter(cls, diameter):
        cls.diameter = diameter
        return cls

diameter is a class (static) variable. However - it looks like it exists as an instance variable and class variable as well.

myCircle = Circle.from_diameter(10)
print Circle.diameter
print myCircle.diameter

Output:

10
10

Why does it work? There is no instance variable diameter. I suppose print myCircle.diameter should throw an error.

Kallz
  • 3,244
  • 1
  • 20
  • 38
Hash Doe
  • 313
  • 2
  • 7
  • 2
    Finding class variables via a class instance is EXACTLY how class methods are found when you call them on an instance. In other words, classes would be completely useless unless they worked this way. – jasonharper Jul 29 '17 at 12:33

2 Answers2

2

There's no instance variable, it's just that name lookup in Python objects first looks into the instance, then, if no match has been found, into the class.

Class instances

A class instance is created by calling a class object (see above). A class instance has a namespace implemented as a dictionary which is the first place in which attribute references are searched. When an attribute is not found there, and the instance’s class has an attribute by that name, the search continues with the class attributes. [...] If no class attribute is found, and the object’s class has a __getattr__() method, that is called to satisfy the lookup.

(Python 2, Python 3)

Community
  • 1
  • 1
Matteo Italia
  • 123,740
  • 17
  • 206
  • 299
1

when you try to access the variable with a class it look into only

cls.__dict__

but when you try to access the variable with instance it looks first

self.__dict__ 

if find then return or if can't find then it also looks in

cls.__dict__

here cls is the class

class Test:
    temp_1=10
    temp_2=20

    def __init__(self):
        self.test_1=10
        self.test_2=20

    @classmethod
    def c_test(cls):
        pass

    def t_method(self):
        pass


print Test.__dict__
print Test().__dict__

Output:

{'c_test': <classmethod object at 0x7fede8f35a60>, '__module__': '__main__', 't_method': <function t_method at 0x7fede8f336e0>, 'temp_1': 10, '__doc__': None, '__init__': <function __init__ at 0x7fede8f335f0>, 'temp_2': 20}

{'test_2': 20, 'test_1': 10}

For detail class special attribute

Kallz
  • 3,244
  • 1
  • 20
  • 38