How objects and class atributtes work

What’s a class attribute

A class attribute is a python variable that belongs to a class rather than a particular object. It is shared between all the objects of this class and it is defined outside the constructor function, __init__(self,...), of the class.

What’s an instance attribute

An instance attribute is a python variable belonging to one, and only one, object. This variable is only accesible in the scope of this object and it is defined inside the constructor function, __init__(self,..) of the class.

The below ExampleClass is a basic python class with two attributes: class_attr and instance_attr.

What are the differences between class and instance attributes

  • instance_attr is an instance attribute defined inside the constructor.
  • class_attr is a class attribute defined outside the constructor.

The instance_attr is only accesible from the scope of an object. The class attribute (class_attr) is accesible as both a property of the class and as a property of objects, as it is shared between all of them.

Notice that the class attribute can be accesed as a class property and as an instance property, however, accesing an instance attribute as a class property raises an AttributeError

So what is a namespace?

In python, a namespaces is a mapping between objects and names. TO keep it simple, let’s say it is a python dictionary that has as a key to the name of the objec and its value as a value.DIfferent namespaces can coexist with the property while the names within them are independiente.

Python classes and objects have different namespaces, for our example, we have ExampleClass.__dict__ as a namespaces for our class and foo.__dict__(bar.__dict__) as a as a namespaces for our object foo(bar)

When you acces an attribute (instance or class attribute) as a property of an object using the dot convention, searches first in the namespaces of that object for that attributte name.If it is found, it returns the value, otherwise, it seraches in the namespaces of the class. If nothing is found theres as well, it raises an AttributeError. The object namespaces is before the class namespaces.

If we find, in one class, both an instance attributte and a class attribute with the same name, the access to that name from your object will get you the value in the object namespaces.Below a simplified version of the lookup function.

When you acces an attribute as a calss property, it searhes directly i the class namespaces for the name of that attribute. If it is found, it returns the value, otherwise, it raises an AttributeError.

Class Attributes Mutate to Be Instance Attributes

Yeah, it might seem weird, but they do! Let’s consider the following scenario and then comment it together.

The class_attr is shared between all the objects of the class. HOmewever, ehen we changed the value from the foo object, this changed is not visible from the bar object which still has the old value, 0, rather than the new value , 5! Hold on … let’s check our namespaces and try to understand what the hell is happening.

The affectation added a new instance attribute to the object foo and only to that object which is why in the previous example the object bar kept printing the class attribute.

With immutbale objects, this behavior is always the same.However, with utbale objects like lits, for example, it is not always the case, depending on how you modify your class attribute.

Let’s change our previous class to have a list as a class attribute.

We mmodify that list as a property of the object foo by appending a new element to it

When a mutable class attribute is modified by an object, it does not mutate to turn into an instance attribute for that object. It stays. shared between all the objects of the class with the new elements appendes to it.

However, if you attach a new list to that attribute ( foo.class_attr = list("foo")) you will get the same behavior as the immutable objects.

You can compare the namespace by yourself as proof of the previous behavior.

Explain __dict__attribute

Basically it contains all the attributes which describe the object under question. It can be used to alter or read the attributes

A dictionary or other mapping object used to store an object’s (writable) attributes.

Remember, everything is an object in python. When I say everything, I mean everything like functions, classes, objects etc (Ya you read it right, classes. Classes are also objects). For example,

output

Conclusion

Python class attribute may be useful in different cases, however, they must be used with caution in order to avoid unexpected behaviors.

Sources: