Home >Backend Development >Python Tutorial >Python class instance attribute access rules
Generally speaking, in Python, the access rules for class instance attributes are relatively intuitive.
However, there are still some things that are not very intuitive, especially for C++ and Java programmers.
Here, we need to understand the following points:
1. Python is a dynamic language, and any entity can dynamically add or delete attributes.
2. A class defines a scope.
3. Class instances also introduce a scope, which is different from the scope defined by the corresponding class.
4. When looking for attributes in a class instance, first search in the scope of the instance itself. If not found, then search in the scope of the class definition.
5. When assigning a value to a class instance attribute, an attribute will actually be added to the scope defined by the class instance (if it does not already exist), and it will not affect the attribute of the same name defined in the corresponding class.
Let’s look at an example below to deepen our understanding of the above points:
class A:
cls_i = 0
cls_j = {}
def __init__(self):
self.instance_i = 0
self. instance_j = {}
Here, we first define an instance a of class A, and then look at what is in the scope of class A and the scope of instance a:
>>> a = A()
>>> a.__dict__
{'instance_j': {}, 'instance_i': 0}
>>> A.__dict__
{'__init__': , '__module__': '__main__', 'cls_i' : 0, 'cls_j': {}, '__doc__': None}
We see that there are instance_i and instance_j in the scope of a, and cls_i and cls_j in the scope of A.
Let’s take a look at how the name lookup occurs:
>>> a.cls_i
0
>>> a.instance_i
0
When looking for cls_i, the scope of instance a is If there is no such thing, it is found in the scope of A; when searching for instance_i, it can be found directly in the scope of a.
What happens if we try to modify the value of cls_i through instance a:
>>> a.cls_i = 1
>>> a.__dict__
{'instance_j': {}, 'cls_i' : 1, 'instance_i': 0}
>>> A.__dict__
{'__init__': , '__module__': '__main__', 'cls_i': 0, 'cls_j': {}, '__doc__': None}
We can see that there is an additional cls_i attribute in the scope of a, and its value is 1; at the same time, we also notice that the value of the cls_i attribute in the scope of A is still 0; here, we are actually An instance attribute is added and the class attribute is not modified.
What if we manipulate the data in cls_j through instance a (note not cls_j itself):
>>> a.cls_j['a'] = 'a'
>>> a.__dict__
{'instance_j': {}, 'cls_i': 1, 'instance_i': 0}
>>> A.__dict__
{'__init__': , '__module__': '__main__', 'cls_i': 0, 'cls_j': {'a': 'a'}, '__doc__': None}
We can see that the scope of a has not changed, but the scope of A has undergone some changes, in cls_j The data has changed.
Changes in the scope of an instance will not affect other instances of the class, but changes in the scope of the class will affect all instances of the class, including instances created before:
>> > A.cls_k = 0
>>> i.cls_k
0