About Mutable Class Attributes

Mutable objects are lists, dictionaries, sets, user-defined classes, and combinations of all of these.

Be aware that modified mutable class attributes have impact on all instances of that class, and that can have unexpected behaviours:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
>>> class Example(object):
...     NUMBERS = [1, 2, 3]
...     def __init__(self, overwrite=False):
...         if overwrite and 2 in self.NUMBERS:
...             self.NUMBERS.remove(2)
...
>>> obj1 = Example()
>>> obj1.NUMBERS
[1, 2, 3]
>>> obj2 = Example(overwrite=True)
>>> obj2.NUMBERS
[1, 3]
>>> obj1.NUMBERS
[1, 3]
>>> obj3 = Example()
>>> obj3.NUMBERS
[1, 3]

Moreover, if you use mutable class attributes for Django forms, the modifications of the attribute might affect not only this request, but also the future requests until the web server is restarted.

To avoid the unexpected behaviour, make the attribute instance-based:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
>>> class Example(object):
...     def __init__(self, overwrite=False):
...         self.NUMBERS = [1, 2, 3]
...         if overwrite and 2 in self.NUMBERS:
...             self.NUMBERS.remove(2)
...
>>> obj1 = Example()
>>> obj1.NUMBERS
[1, 2, 3]
>>> obj2 = Example(overwrite=True)
>>> obj2.NUMBERS
[1, 3]
>>> obj1.NUMBERS
[1, 2, 3]
>>> obj3 = Example()
>>> obj3.NUMBERS
[1, 2, 3]

Tips and Tricks Programming Django 4.x Django 3.2 Django 2.2 Python 3