About Class vs Instance Attributes
In Python, class attributes and instance attributes are two different things. When you try to access an attribute of an instance, the lookup prioritizes instance attribute at first and falls back to the class attribute.
For example, having this class:
class Book:
pages = 0
def __init__(self, pages=None):
if pages:
self.pages = pages
You would retrieve the pages either from the instance or the class:
>>> book1 = Book()
>>> book1.pages # reading from the class
0
>>> book2 = Book(pages=300)
>>> book2.pages # reading from the instance
300
Instance attributes are stored in the __dict__ attribute. Class attributes are within the mapping proxy __dict__ of the class. Here's an example:
>>> book1.__dict__
{}
>>> book2.__dict__
{'pages': 300}
>>> Book.__dict__["pages"]
0
There is an important gotcha: if the class attribute has a mutable value such as a list, dictionary, or an instance of another class, and you modify its content, it will affect all the instances of the class, unless the instance attribute is overwritten.
For example, having this class:
class Bag:
items = []
The behavior will surprise you:
>>> paper_bag = Bag()
>>> plastic_bag = Bag()
>>> paper_bag.items.append("bananas")
>>> plastic_bag.items
['bananas']
Therefore, assign the mutable attributes to the instance, not classes:
class Bag:
def __init__(self):
self.items = []
Also by me
Django Paddle Subscriptions app
For Django-based SaaS projects.
Django GDPR Cookie Consent app
For Django websites that use cookies.