In Python, the access rules of class instance attributes are relatively intuitive. in Python, the access rules of class instance attributes are relatively intuitive.
However, there are still some inintuitive points, especially for C ++ and Java programmers.
Here, we need to understand the following:
1. Python is a dynamic language. any entity can dynamically add or delete attributes.
2. a class defines a scope.
3. the class instance also introduces a scope, which is different from the scope defined by the corresponding class.
4. when you search for attributes in a class instance, you first search for attributes in the instance's own scope. if the attributes are not found, you can search for attributes in the scope defined by the class.
5. when assigning values to class instance attributes, an attribute is actually added to the scope defined by the class instance (if it does not exist), and the attributes with the same name defined in the corresponding class are not affected.
Let's take an example to better understand the above:
Class:
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 the scope of Class A and the scope of instance a in what are different:
>>> A = ()
>>> A. _ dict __
{'Instance _ j': {}, 'instance _ I ': 0}
>>> A. _ dict __
{'_ Init _':, '_ module _': '_ main _', 'cls _ I ': 0, 'cls _ j ': {}, '_ doc _': None}
We can see that instance_ I and instance_j are in the scope of a, and cls_ I and cls_j are in the scope of.
Let's take a look at how the name search happens:
>>> A. cls_ I
0
>>> A. instance_ I
0
When searching for cls_ I, instance a does not have its scope, but it is found in the scope of instance A. When searching for instance_ I, you can find it directly in the scope of.
What if we try to modify the cls_ I value through instance:
>>> 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 a cls_ I attribute in the scope of A, and its value is 1. at the same time, we also note that the value of the cls_ I attribute in the scope of a is still 0. here, we actually added an instance attribute and did not modify it to the class attribute.
What if we use instance a to manipulate the data in cls_j (note that it is 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 changed, and the data in cls_j has changed.
The instance scope changes and does not affect other instances of the class. However, changes in the scope of the class affect all instances of the class, including the instances created before this:
>>> A. cls_k = 0
>>> I. cls_k
0