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