Usually, when we access classes or instance objects, we involve some magic methods of accessing attributes, including:
_u getattr_ (self, name): Called when accessing an attribute that does not exist
(2) u getattribute_ (self, name): Call when accessing an existing property (call this method first to see if the property exists, and then call if it does not exist)
(3) u setattr_ (self, name, value): Called when setting a new property of the instance object
(4) u delattr_ (self, name): Called when the attribute of an instance object is deleted
To verify the above, the code is listed as follows:
1 class Test: 2 def __getattr__(self, name): 3 print('__getattr__') 4 5 def __getattribute__(self, name): 6 print('__getattribute__') 7 8 def __setattr__(self, name, value): 9 print('__setattr__') 10 11 def __delattr__(self, name): 12 print('__delattr__') 13 14 >>> t=Test() 15 >>> t.x 16 __getattribute__
As shown in the above code, x is not an attribute of the Test class instance t. First, we call the u getattribute_() method to know that this attribute does not belong to the instance object; however, according to common sense, t.x should print u getattribute_ and u getattr_, but this is not the case, why? Is the Python rule invalid?
Don't worry, listen to me speak slowly!
The order of finding instance object attributes is as follows:
(1) First access the u getattribute_() magic method (implicit default call, which will be called in any case)
(2) Find out whether it has the attribute in the instance object t: Find in t. u dict_, each class and instance object has a u dict_ attribute.
(3) If the corresponding attributes cannot be found in t. dict_, then the attributes can be found in the class of the instance, that is, T. class. Dict_u
(4) If the attribute is not found in the class of the instance, it is found in the parent class, that is, T. class. Bases. Dict.
(5) If none of the above can be found, the u getattr_ method will be called to execute internal commands (if the u getattr_ method is not overloaded, the direct error will be reported: AttributeError)
The above processes, that is, to complete the search for attributes.
However, the above statement does not explain why'u getattr_'is not printed when t.x is executed.
You see, it's urgent. As a programmer ape, you must have patience uuuuuuuuuuuu
The problem arises in step 4, because once the u getattribute_() method is overloaded, if the attribute cannot be found, step 4 must be added manually, otherwise step_u getattr_ cannot be entered.
Verify that the above statement is correct:
Method 1: Use object (base class of all classes)
1 class Test: 2 def __getattr__(self, name): 3 print('__getattr__') 4 5 def __getattribute__(self, name): 6 print('__getattribute__') 7 object.__getattribute__(self, name) 8 9 def __setattr__(self, name, value): 10 print('__setattr__') 11 12 def __delattr__(self, name): 13 print('__delattr__') 14 15 16 >>> t=Test() 17 >>> t.x 18 __getattribute__ 19 __getattr__
How do you show it? Ha-ha
Method 2: super() method was used.
1 class Test: 2 def __getattr__(self, name): 3 print('__getattr__') 4 5 def __getattribute__(self, name): 6 print('__getattribute__') 7 super().__getattribute__(name) 8 9 def __setattr__(self, name, value): 10 print('__setattr__') 11 12 def __delattr__(self, name): 13 print('__delattr__') 14 15 16 >>> t=Test() 17 >>> t.x 18 __getattribute__ 19 __getattr__
Ha-ha, mayonnaise purple can also be oh ^ v ^
So what's the difference between method one and method two? If you look closely, you will find that there is only a small difference:
1 #Method 1: Use base classes object Method 2 def __getattribute__(self, name): 3 print('__getattribute__') 4 object.__getattribute__(self, name) 5 6 #Method 2: Use super()Method (Some think) super()Is a class, which is handled by method for the time being) 7 def __getattribute__(self, name): 8 print('__getattribute__') 9 super().__getattribute__(name)
In Python 2.x, the use of the above super should be changed to super (Test, self). x x x x, but in 3.x, it can be used as simply as the code above.
So what is super? If you want to understand in detail, please click Here
Haha, after the above introduction, the u setattr_ and u delattr_ methods are relatively simple:
1 class Test: 2 def __getattr__(self, name): 3 print('__getattr__') 4 5 def __getattribute__(self, name): 6 print('__getattribute__') 7 object.__getattribute__(self, name) 8 9 def __setattr__(self, name, value): 10 print('__setattr__') 11 12 def __delattr__(self, name): 13 print('__delattr__') 14 15 16 >>> t=Test() 17 >>> t.x=10 18 __setattr__ 19 >>> del t.x 20 __delattr__
So far, let's get to a conclusion about attribute access, followed by a more advanced descirptor.