Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python : Using class variables incorrectly?

Tags:

python

I have the following classes:

class A(object):
    x = 1
class B(A):
    pass
class C(A):
    pass

When I print the value of x from each class I get:

>>>A.x, B.x, C.x
(1,1,1)

Then I assign 2 to B.x

B.x = 2
A.x, B.x, C.x
>>>(1,2,1)

Everything was normal but when I assigned 3 to A.x I got this :

A.x=3
A.x, B.x, C.x
>>>(3,2,3)

I thought it would return (3,2,1).

like image 966
zazz Avatar asked Apr 30 '21 04:04

zazz


People also ask

Can you change class variable in Python?

We should be careful when changing the value of a class variable. If we try to change a class variable using an object, a new instance (or non-static) variable for that particular object is created and this variable shadows the class variables. Below is a Python program to demonstrate the same.

Are class variables shared between instances?

var should definitely not be shared as long as you access it by instance. var or self. var . With the list however, what your statement does is when the class gets evaluated, one list instance is created and bound to the class dict, hence all instances will have the same list.

Can you change class variables?

Any object can change the value of a class variable, but class variables can also be manipulated without creating an instance of the class.

How do you declare a class variable in Python?

In Python, Class variables are declared when a class is being constructed. They are not defined inside any methods of a class because of this only one copy of the static variable will be created and shared between all objects of the class.

What is a class variable in Python?

Class Variables: A class variable is a variable that is declared inside of class, but outside of any instance method or __init__ () method. Instance variable vs. class variables What is an Class Variable in Python? What is an Class Variable in Python?

What is a static variable in Python?

Class or Static Variables in Python. Class or static variables are shared by all objects. Instance or non-static variables are different for different objects (every object has a copy of it). For example, let a Computer Science Student be represented by class CSStudent.

What is the difference between instance and class variables in Python?

Class variables are shared by all instances of a class. Unlike instance variable, the value of a class variable is not varied from object to object, In Python, Class variables are declared when a class is being constructed.

How to define variables outside of a class in Python?

In Python, we can define the variable outside the class, inside the class, and even inside the methods. Let’s see, how to use and access these variables throughout the program. The variables that are defined outside the class can be accessed by any class or any methods in the class by just writing the variable name.


Video Answer


1 Answers

This is fundamentally how inheritance works in Python: for class-level variables, it first checks' the classes namespace, then the namespace of every class in the method resolution order. So, both B and C inherit x from A:

In [1]: class A(object):
   ...:     x = 1
   ...: class B(A):
   ...:     pass
   ...: class C(A):
   ...:     pass
   ...:

In [2]: vars(A)
Out[2]:
mappingproxy({'__module__': '__main__',
              'x': 1,
              '__dict__': <attribute '__dict__' of 'A' objects>,
              '__weakref__': <attribute '__weakref__' of 'A' objects>,
              '__doc__': None})

In [3]: vars(B)
Out[3]: mappingproxy({'__module__': '__main__', '__doc__': None})

In [4]: vars(C)
Out[4]: mappingproxy({'__module__': '__main__', '__doc__': None})

When you ask for B.x or C.x, it looks into that class namespace, doesn't find any "x", then tries A's namespace, finds it, and returns it.

Now, when you assign a variable to B.x = 2, that adds it to B's class namespace directly:

In [5]: B.x = 2
   ...:

In [6]: vars(B)
Out[6]: mappingproxy({'__module__': '__main__', '__doc__': None, 'x': 2})

And similarly, when you assign it to A.x=3, it overwrites the old value:

In [7]: A.x=3
   ...:

In [8]: vars(A)
Out[8]:
mappingproxy({'__module__': '__main__',
              'x': 3,
              '__dict__': <attribute '__dict__' of 'A' objects>,
              '__weakref__': <attribute '__weakref__' of 'A' objects>,
              '__doc__': None})

In [9]: vars(B)
Out[9]: mappingproxy({'__module__': '__main__', '__doc__': None, 'x': 2})

In [10]: vars(C)
Out[10]: mappingproxy({'__module__': '__main__', '__doc__': None})

So now, same as before, when you look for C.x, it doesn't find it's own, then it looks for x inside A, and finds it.

Note, inheritance works like this with instances too, just it checks the instance namespace first, then the instances class's namespace, then all the namespace of the classes in it's method resolution order.

like image 181
juanpa.arrivillaga Avatar answered Nov 10 '22 15:11

juanpa.arrivillaga