Python Notes (4) class (top) properties and descriptors

Source: Internet
Author: User

Partial reference from: http://www.geekfan.net/7862/

New class and Classic class

2 and 3 are not the same, 3 are new classes.

The difference between a new class and a classic class:

Class A: #classic Class "" "This is    Class A" ""    Pass    __slots__= (' x ', ' y ')    def Test (self):        # Classic class Test "" "This is        a.test ()" ""        print "A class" Class B (Object): #new class "" "" The Is    class B "" "    __slots__= (' x ', ' y ')    pass    def test (self):        # New class Test" "" This is        b.test ()        "" " Print "B class"        if __name__ = = ' __main__ ':    a=a ()    b=b ()    print dir (a)    print dir (B)
[' __doc__ ', ' __module__ ', ' __slots__ ', ' Test '] [' __class__ ', ' __delattr__ ', ' __doc__ ', ' __format__ ', ' __getattribute__ ', ' __hash__ ', ' __init__ ', ' __module__ ', ' __new ' __ ', ' __reduce__ ', ' __reduce_ex__ ', ' __repr__ ', ' __setattr__ ', ' __sizeof__ ', ' __slots__ ', ' __str__ ', ' __subclasshook__ ' ', ' Test ', ' x ', ' Y ']

New class to indicate the parent class, the above code class B declares that his parent class is object.

Python is a dynamic language, and you can add properties dynamically.

>>> a.x = 1>>> a<__main__. A instance at 0x05bbb620>>>> a.x1

__slots__ slots, properties restrict instance B to add only X, Y properties, A is a classic class, you can continue adding, but B is a new class that cannot continue to be added.

>>> a.z = 2>>> a.z2>>> b.z = 2Traceback (most recent call last):  File "<stdin>", line 1, in <module>attributeerror: ' B ' object have no attribute ' Z '

  

>>> Help (a) Help on instance for a in module __main__:class a |  This is class A |   |  Methods defined here: |   |  Test (self) |      This was A.test () >>> help (b) Help on B in module __main__ object:class B (__builtin__.object) |  This is class B |   |  Methods defined here: |   |  Test (self) |      This is b.test () |   |  ---------------------------------------------------------------------- |  Data descriptors defined here: |   |  x |   |  Y

Class B because it is a new type of __slots__ is working, try to use the new class, because so python2,3 can run.

Properties and encapsulation instance types

__init__ double underline is a special method, __init__ defines an instance property, Owner,country is an instance property, and country is a class property.

Invoke instance properties, such as class properties and instance property names, when called. If there are no instance attributes, go to find out if the class attribute is present.

Class Car (object):    country = u ' China '     def __init__ (self,owner=none):        self.owner = owner        self.country = " China "if __name__ = = ' __main__ ':    a = Car (U ' Xiao Zhang ')    print a.country        a.country = U ' Us '        print a.country    Print "--------------------------"    del a.country    print A.country
>>> USA--------------------------China
Private properties

Private properties are visible only inside the function. It is assigned a value change by the Get,set method.

Add two underscores to the variable before it can be accessed indirectly, with only one underscore _ module privatization. The two underline __ before and after the variable is the property that comes with the system.

Class Car (object):    def __init__ (self,owner=none):        Self.__owner = owner    def getOwner (self):        return Self.__owner    def setowner (self, value):        Self.__owner = valueif __name__ = = ' __main__ ':    a = Car (U ') Blackboard Guest ')    print A.getowner ()

  

>>> A.ownertraceback (most recent):  File ' <stdin> ', line 1, in <module>attributeerror : ' Car ' object has no attribute ' owner ' >>> a.getowner () u ' \u9ed1\u677f\u5ba2 ' >>> dir (a) [' _car__owner ' , ' __class__ ', ' __delattr__ ', ' __dict__ ', ' __doc__ ', ' __format__ ', ' __getattribute__ ', ' __hash__ ', ' __init__ ', ' __ module__ ', ' __new__ ', ' __reduce__ ', ' __reduce_ex__ ', ' __repr__ ', ' __setattr__ ', ' __sizeof__ ', ' __str__ ', ' __ Subclasshook__ ', ' __weakref__ ', ' getOwner ', ' SetOwner ']>>> a._car__owneru ' \u9ed1\u677f\u5ba2 '

  

Descriptor Adorner Descriptor

@property @xx. Setter @xx. deleter

You can turn the Get,set method into a property access.

Class Car (object):    def __init__ (self,owner=none):        self._owner = owner     @property    def owner (self):        return Self._owner    @owner. Setter    def owner (self, value):        Self._owner = value    @owner. deleter    def owner:        self._owner = None    if __name__ = = ' __main__ ':    a = Car (U ' you Uncle ')    print a.owner< C14/>del a.owner    Print A.owner
Your uncle None.

Such an owner Get,set,del to define three, if there are other attributes, then need three, which will produce redundancy, duplicate code.

__getattr__, __setattr__, __delattr__

__getattr__ The attribute is not found in the __dict__ and _class__.__dict__ of the variable, the __getattr__ is called and, if any, the value in __dict__ is called directly.

__setattr__ variable Assignment

__DELATTR__ Deleting a variable

Class Car (object):    country = u ' China '    #__slots__ = (' Length ', ' width ', ' height ', ' owner ', ' __dict__ ')        def __ Init__ (self, length, width, height, owner=none):        self.owner = owner        self.length = length        self.width = width< C6/>self.height = height            def __getattr__ (self,name):        print "__getattr__", name        return Self.__dict__.get ( Name,none)            def __setattr__ (self,name,value):        print "__setattr__", name        if name!= ' owner ':            Assert value>0, name+ "must larger than 0"        self.__dict__[name]=value            def __delattr__ (self,name):        Print "__delattr__", name        if name== ' owner ':            self.__dict__[name]=none            if __name__ = = ' __main__ ':    A = Car (1.2,1.4,1.5,u ' er ye ')

Output:

__setattr__ owner__setattr__ length__setattr__ width__setattr__ Height

Add __slots__ after, because can access __setattr__ so can be arbitrary add attribute without error, to make slots have effect, you have to change the code in the __setattar__:

    def __getattr__ (self,name):        print "__getattr__", name        assert name in self.__slots__, "not has this attribute" + Name        return Self.__dict__.get (name,none)            def __setattr__ (self,name,value):        print "__setattr__", name        assert name in self.__slots__, "not has this attribute" +name                if name!= ' owner ':            assert value>0, name+ "Mu St larger than 0 "        self.__dict__[name]=value            def __delattr__ (self,name):        print" __delattr__ ", name        assert name in self.__slots__, "not has this attribute" +name        if name== ' owner ':
Class Descriptor

The descriptor can be used as a property of the class, and the data descriptor __get__,__set__,__del__.

Class Positivenum (object): Def __init__ (self): Self.default = 1 Self.data = {} def __get__ (self, inst ance, owner): # instance = x # owner = type (x) print "__get__", Instance,owner return Self.data . Get (instance, Self.default) def __set__ (self, instance, value): # instance = x print "__set__", instance            , Value Try:assert int (value) >0 self.data[instance] = value except Assertionerror:        Print "ERROR:" +str (value) + "is not positive number."                Except:print "ERROR:" +str (value) + "is not number value."     def __delete__ (self,instance): print "__delete__", Instance del Self.data[instance] class Car (object): Country = U ' China ' length = positivenum () width = positivenum () height = Positivenum () __slots__= (' owner ', ' Le Ngth ', ' width ', ' height ') def __init__ (self, length, width, height, owner=none): Self.owner = Owner        Self.length = Length Self.width = width self.height = Height if __name__ = = ' __main__ ': a = Car (1.2,1.4,1.5,u ' blackboard guest ') B = car (2.2,2.4,2.5,u ' xiaoming ') print a.length a.length=1

When the interpreter encounters print a.length, it takes length as a descriptor with a __get__ method, invokes the A.length.__get__ method and prints the return value of the method, which is similar to the property above. __GET__ receives two parameters: instance instance object, this is a in a.length, and the other is the type car of the instance. In some documents, car is referred to as the owner of a descriptor (owner). If you need access to Car.length,python, you will call Car.length.__get__ (None,car). You can see that the first parameter is either an instance or none.

When the interpreter sees A.length = 1 o'clock, Python recognizes that length is a descriptor with the __set__ method, so it calls a.length.__set__ (a,100), the first argument instance is the instance, and the second is the assignment.

CAR.LENGTH.__DELETE__ (a) when deleted.

Each positivenum maintains a dictionary that holds the mappings between the owner instance and the corresponding data. When A.length is called, the __get__ method finds the data associated with a and returns a default value if it does not exist. The __set__ is in the same way, but it contains additional illegal checks.

Descriptors Act on the hierarchy of classes, and each instance of a class shares the same descriptor. So different instance objects have to be manually managed in different states and need to be displayed to accurately pass parameters to the __get__,__set__ and __delete__ methods.

If you remove data = {} from Positivenum, because descriptors are class-based, they share the same class attribute, which is why you use a dictionary. The __get__,__set__ parameter also indicates which instance to use as the dictionary key.

Error Example:

Class Positivenum (object): Def __init__ (self,value): Self.val = value def __get__ (self, instance, owner): # instance = A, b # owner = Car print "__get__", Instance,owner return self.val def __set__ (SE LF, instance, value): # instance = A, b print "__set__", instance,value Try:assert Int (valu e) >0 self.val = value except Assertionerror:print "ERROR:" +str (value) + "is not positive        Number. "                  Except:print "ERROR:" +str (value) + "is not number value." def __delete__ (self,instance): print "__delete__", instance self.val = None #def __getattribute__ (Self,nam E): #print Self, Name Class Car (object): Country = U ' China ' length = positivenum (0) width = positivenu  M (0) height = positivenum (0) #__slots__ = (' owner ', ' Length ', ' width ', ' height ') def __init__ (self, length, width, Height, owner=none): Self.owner = OWner self.length = Length Self.width = width self.height = Height if __name__ = = ' __main__ ': A = car (1.2,1.4,1.5,u ' blackboard passenger ') b = car (2.2,2.4,2.5,u ' xiaoming ')

  

A.length__get__ <__main__. Car object at 0x098e61b0> <class ' __main__. Car ' >out[39]: 2.2b.length__get__ <__main__. Car object at 0x098e6230> <class ' __main__. Car ' >out[40]: 2.2

Although a defines 1.2, it also becomes 2.2 because it has a class property with B.

Python Notes (4) class (top) properties and descriptors

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.