The descriptor in Python

Source: Internet
Author: User

To learn and use good Python, descriptor is a point that must span the past, and now, although Python books are a lot of tricks, but it seems to be introduced in some Python libraries, the Python language itself is very little attention, or even attention, but can introduce the Dscriptor introduced clearly, is very few, to the present, I have not seen.

A attr can be referred to as descriptor, except for the need to define descriptor protocol prescribed methods, this attr must belong to a class, not belong to a certain instance

First, the descriptor in Python

Overriding any of the following methods in a Python class is called descriptor

1.__get__ (self,obj,type=none)---->value

2.__set__ (self,obj,value)---->none

3.__DELETE__ (self,obj)---->none

Descriptor Subdivision:

1.Data descriptor: Just rewrite __get__,__set__ 's class

2.None Data Descriptor: Just rewrite the __get__ class.

3.read-only Data Descriptor also defines __get__,__set__, but this __set__ is just raise attributeerror

The difference between data descriptor and none Data descriptor: The precedence relative to the instance dictionary.

If the instance dictionary has the same name as the descriptor, if the descriptor is a data descriptor, the data descriptor is given precedence, and if the descriptor is a non-data descriptor,

The attributes in the dictionary are used first. Example of this rule in practice: If the instance has the same name as the method and the attribute, Python takes precedence over the attributes in the instance dictionary.

Because the implementation of an instance function is a non-data descriptor.

Second, through instance access attributes:

Instance.a

__getattribute__,__getattr__,__get__ and __dict__ are all related to property access and their precedence:

1. When the __getattribute__ method is defined in the class (type (instance)), the __getattribute__ is called unconditionally. So in the __getattribute__ method, you cannot appear self.__attr__ This invocation, which causes unrestricted recursion

2. If the accessed attr exists and the attr is of type (instance) or is a parent of type (Instace) (super class is not metaclass), And this attr is a descriptor, then the call will continue to class.__get__ accordingly. Nutshell:

2.1 This attr is a descriptor that calls this property __get__

2.2 This attr is not a descriptor, call __dict__[attr]

3. If the property is not defined in the class, call __getattr__

4. Otherwise, throw an exception attributeerror

    • Experiment one: In SELF.__DICT__ can obtain a compliance with the descriptor attr, this attr is not a descriptor, so do not comply with the descriptor rules
Class Datadescriptor (object):d EF __get__ (self,obj,owner):p rint ("datadescriptor.__get__", Self,obj,owner) return 2class A (object):p Assclass B (a):d ef __init__ (self): Self.datadescriptor=datadescriptor () a=b () print A.datadescriptor #输出 <__main__. Datadescriptor Object at 0x00bd8db0>
    • Experiment two: Get attr in class.__dict__, and this attr is a descriptor
Class Datadescriptor (object):d EF __get__ (self,obj,owner):p rint ("datadescriptor.__get__", Self,obj,owner) return 2class A (object):d Atadescriptor=datadescriptor () class B (A):d ef __init__ (self):p assa=b () print a.datadescriptor "output (' datadescriptor.__get__ ', <__main__. Datadescriptor object at 0x00bd8cf0> <__main__. B object at 0x00bd8d50>, <class ' __main__. B ' >) '
    • Experiment three: __getattribute__ return non-descriptor

Class Datadescriptor (object):d EF __get__ (self,obj,owner):p rint ("datadescriptor.__get__", Self,obj,owner) return 2class A (object):d Atadescriptor=datadescriptor () class B (A):d ef __init__ (self):p assdef __getattribute__ (self,name): Print ("b.__getattribute__  name=", name) return "ABC" A=B () print a.datadescriptor ' ' Output: (' b.__getattribute__  Name= ', ' Datadescriptor ') ABC '

 

    • Experiment four: __getattribute__ return to descriptor, obey descriptor rules
def __get__ (Self,obj,owner):p rint ("datadescriptor.__get__", Self,obj,owner) return 2class A (object):d atadescriptor= Datadescriptor () class B (A):d ef __init__ (self):p assdef __getattribute__ (self,name):p rint ("b.__getattribute__  Name= ", name) return type (self). Datadescriptora=b () Print A.datadescriptor" Output: (' b.__getattribute__  name= ', ' Datadescriptor ') (' datadescriptor.__get__ ', <__main__. Datadescriptor object at 0x00bd8cb0>, None, <class ' __main__. B ' >) 2 "
    • Experiment five, in the case where attr is not found

This is a special case, return none in __getattribute__ or no return statement, will not be called, only in __getattribute__ raise Attributeerror (), only call __ getattr__, if no __getattribute__ is defined, the VM defaults to raise Attributeerror () If attribute is not found.

Code 1

Class Datadescriptor (object):d EF __get__ (self,obj,owner):p rint ("datadescriptor.__get__", Self,obj,owner) return 2class A (object):d Atadescriptor=datadescriptor () class B (A):d ef __init__ (self):p assdef __getattribute__ (self,name): Print ("b.__getattribute__  name=", name) raise Attributeerror () #return nonedef __getattr__ (self,name):p rint ("B._ _getattr__ name= ", name) return" Not Found "a=b () Print A.datadescriptor ' ' defines __getattribute__, but raise Attributeerror, So will continue to call to __getattr__, no no raise attributeerror, no matter what __getattribute__ did, will not continue to call __getattr__ ""

Code 2

Class Datadescriptor (object):d EF __get__ (self,obj,owner):p rint ("datadescriptor.__get__", Self,obj,owner) return 2class A (object):d Atadescriptor=datadescriptor () class B (A):d ef __init__ (self):p ass#def __getattribute__ (self,name) : #print ("b.__getattribute__  name=", name) #raise attributeerror () #return nonedef __getattr__ (self,name):p rint (" b.__getattr__ name= ", name) return" Not Found "a=b () Print a.zz ' ' cannot find ZZ This ATTR,VM default raise Attributeerror, automatically calls __getattr __‘‘‘

Third, access attributes through class

Using class object to get attr is conceptually the same as getting properties through instance, instance class is a class object, and class object class should be the class Metaclass

When attr is not found in the Dict of class object, it is turned to the Metaclass dict of class.

The rules for accessing properties through Classa.attr are:

    1. If there is __getattribute__ in Metaclass, the result of the __getattribute__ is returned directly.
    2. If attr is a descriptor, the result of the __get__ of descriptor is returned directly.
    3. If attr is a property in Class.dict, the value of attr is returned directly
    4. If there is no attr in the class and __getattr__ is defined in Metaclass, the __getattr__ in Metaclass is called
    5. Throws an exception if there is no attr in the class and __getattr__ is not defined in Metaclass attributeerror
    • Experiment
Class Metaclass (Type):d atadescriptor=datadescriptor () def __new__ (metaclz,name,bases,attrs):p rint ("Create new class ", Metaclz,name) return type.__new__ (METACLZ, name, bases, Attrs) def __getattr__ (self,name):p rint (" metaclass.__ getattr__ name: ", name) #def __getattribute__ (self,name): #print (" metaclass.__getattribute__ name: ", name) #return name + ' A ' class ClassB (object): __metaclass__=metaclassprint classb.datadescriptorprint classb.ss ' ' Output (' Create new class ', <class ' __main__. Metaclass ', ' ClassB ') (' datadescriptor.__get__ ', <__main__. Datadescriptor object at 0x00bd8ef0>, <class ' __MAIN__.CLASSB ';, <class ' __main__. Metaclass ' > 2 (' metaclass.__getattr__ name: ', ' SS ') None '

  

The descriptor in Python

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.