3

Suppose I want to implement common variable among objects using class variables (similar to static in java/c++).

When I access class variable using object, it shows default value. Then I updaded class variable via object, its not updating class variable for other objects. It is showing old value in when class variable accessed via other objects or Class Name directly.

Why is it so, and what is the way in python to make class/static variable (common among objects)

# Class for Computer Science Student
class CSStudent:
    
    stream = 'cse'               # Class Variable
    def __init__(self,name):
        self.name = name     # Instance Variable

# Objects of CSStudent class
a = CSStudent('Geek')
b = CSStudent('Nerd')


print(a.stream) # prints "cse"
print(b.stream) # prints "cse"
print(a.name) # prints "Geek"
print(b.name) # prints "Nerd"

# Class variables can be accessed using class
# name also
print(CSStudent.stream) # prints "cse"

# Now if we change the stream for just a it won't be changed for b
a.stream = 'ece'
b.stream = 'abc'
print(CSStudent.stream)  # prints 'ece'
print(a.stream) # prints 'ece'
print(b.stream) # prints 'abc'
2

1 Answer 1

3

You need to know the lookup procedure.

First off, both instances and classes have their own namespaces. Only the class variables are shared between all instances. The namespace of classes and instances are accessible via __dict__ attribute.

When you access an attribute from an instance, Python first looks at the namespace of the instance, if it can find it, it returns it, otherwise it's gonna find it in its class!

class CSStudent:
    stream = "cse"

a = CSStudent()
b = CSStudent()
print("stream" in a.__dict__)          # False
print("stream" in b.__dict__)          # False
print("stream" in CSStudent.__dict__)  # True

print(a.stream)  # cse
print(b.stream)  # cse

So a and b doesn't have that stream, only the class has.

Now a.stream = "something" will add that attribute to the namespace of that specific instance.

a.stream = "something"
print("stream" in a.__dict__)          # True
print("stream" in b.__dict__)          # false
print("stream" in CSStudent.__dict__)  # True

Now if you access a.stream it finds it in the namespace of a and returns it, but because b doesn't have that, it will find it in the class.(the shared one)

print(a.stream)  # something
print(b.stream)  # cse

If you want to the change to reflect all instances, you need to change it on the class which has it shared between all instances.

class CSStudent:
    stream = "cse"

a = CSStudent()
b = CSStudent()
print(a.stream)     # cse
print(b.stream)     # cse
CSStudent.stream = "something"
print(a.stream)     # something
print(b.stream)     # something

Always think about who has what. Then consider the precedence, instance namespaces are checked first.

Note: I simplified the explanation by not mentioning what descriptors are because we don't have one here. Take a look at it later. You would be surprised to see that in fact always class namespaces are checked first!

Sign up to request clarification or add additional context in comments.

2 Comments

thanks for the detailed explanation. But I am still wondering what the correct way is to implement Class Variable common among objects.
@VinayVishwakarma It depends on how you define "correct".Basically if you wanna have a variable that is shared between all the instances,you define it at class level.This way you save memory by not creating that object N times in N namespaces, only once inside the class namespace.But this means that if one instance, changes that variable, all other instances will see the change.In that case, if an instance want to have different value for that variable,it's better to define the new attribute at instance level so that other instances still get theirs from the class which has the original value.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.