How object and class attributes work in Python?

Hadir Jenni
4 min readJan 11, 2021
Python

Object-Oriented Programming(OOP) is basically one way of programming usually implemented in high-level languages; another type is procedural programming. Another manner of seeing OOP, is like giving life to the objects that surround you and me, and being able to create, modify and delete them whenever you want. Python accepts both of these types. Classes and objects are used when using this type of programming, this is way it was important to define this first. Let’s start with

What’s a class attribute?

Now we can define what a class attribute is. This kind of attribute is a characteristic that defines the class, not directly the object. It is not defined in the constructor method (__init__), since the class attribute refers only to the attributes defined in the class.

class example:
counter = 0

def __init__(self):
example.counter += 1
m = example()
n = example()
print(m.counter)
# 2

What’s an instance attribute?

On the other hand, there’s another type of attribute named: Instance attribute. This attribute belongs only to one object, that’s why it receives that name; and it is defined inside of the constructor.

class Example:
counter = 0

def __init__(self, name):
Example.counter += 1
self.name = name
m = Example("Mike")
n = Example("James")
print(m.name)
# 'Mike'
print(n.name)
# 'James'

What are all the ways to create them and what is the Pythonic way of doing it?

To understand better their concept and how they created here’s an example of the Pythonic way:

class ClassName():
class_attr = 0
def __init__(self, instance_attr):
self.instance_attr = instance_attr

What are the differences between class and instance attributes?

One difference between these attributes is where they are defined. The class attribute is defined outside of the constructor, and the instance attribute is defined inside. Another difference is that the class attribute is shared by all instances. The instance attribute is unique to that instance only. For last, it’s important to highlight the fact that if you change a class attribute it will override all of the instances (objects) created.

What are the advantages and drawbacks of each of them?

Advantages and drawbacks of class attributes:

Advantages:

  • All instances of the class inherit them from the class.
  • They store data that is relevant to all the instances. For example, we could have a counter class attribute that increments every time we create a new instance and decrements every time we delete an instance. This way we can always keep track of how many instances of the same class we created.

Drawbacks:

  • It can get messy when you create an instance in which the value of the class attribute is different than the class attribute value, and then try to retrieve it through another instance. The behavior quickly becomes unexpected.
  • It’s not possible to have two instances with different values. So you can’t use them to do different things on different objects. If the Person class only had class attributes, we would not be able to make a contact list with different people in it.

Advantages and drawbacks of instance attributes:

Advantages:

  • They are specific to an object and are easy to set and get thanks to properties.
  • They are discarded once the instance is deleted, so they die with the instance they are associated with, which makes things clearer.

Drawbacks:

  • They don’t allow keeping track of values in between instances.
  • The fact that their values are lost on deletion is also a disadvantage in some cases where you want to keep a history of values for example.

How does Python deal with the object and class attributes using the __dict__ (Dictionary)?

A special attribute of every module is __dict__. This is the dictionary containing the module’s symbol table. object.__dict__ A dictionary or other mapping object used to store an object’s (writable) attribute. So if you want to check all of your class attributes, you can use the special method __dict__ to list them.

class Example:
...print(Example.__dict__)
# mappingproxy({'__module__': '__main__', 'counter': 0, '__init__': <function Example.__init__ at 0x10148e598>, 'name': <property object at 0x1014969a8>, '__dict__': <attribute '__dict__' of 'Example' objects>, '__weakref__': <attribute '__weakref__' of 'Example' objects>, '__doc__': None})
Pythonic goodbye

Sources:

--

--