First,
__call__
object is appended with parentheses, triggering the method below the execution class __call__
.
When an object is created, the object = Class name (), and the execution of the __call__
method is triggered by parentheses after the object, that is: Object () or Class () ( )
Class Foo: ? def __call__ (self, *args, **kwargs): print ("I'm doing it") ? f = Foo () f () #对象加括号调用执行类下的__call__方法
Second,
__next__
and
__iter__
implement the iterator protocol
An iterator protocol is an object that must provide a next method that either returns the next item in the iteration, or causes a Stopiteration exception to terminate the iteration (only backward cannot go forward)
The result of an iterative object execution obj.__iter__()
is an iterator object.
In a class, if there are __iter__
and __next__
built-in methods, then the iterator is formed.
Example
Class Foo: ? def __init__ (self,n): SELF.N = n ? def __iter__: return self #实例本身就是迭代对象, so go back to yourself ? def __next__ (self): if SELF.N >10: raise stopiteration #如果超过10就报StopIteration error SELF.N = SELF.N + 1 return SELF.N ? f = Foo (7) for I in F: #for循环自动调用__next__方法, implements the iteration value print (i)
Example 2
Fibonacci Cinapo sequence in output 100
Class F: ? def __init__ (self): self.a = 0 self.b = 1 ? def __iter__ (self): return to self ? def __next__ (self): self.a, self.b = self.b, SELF.A + self.b if SELF.A >: raise Stopiteration Return SELF.A ? f = f () for I in F:
Third, descriptor (
__get__,__set__,__delete__
)
Descriptor (descriptor):
1. Descriptor Nature
is a new class, in this new class, at least, the __get__()
__set__()
__delete__()
One, which is also known as the Descriptor protocol. : Trigger When an attribute is invoked: When a property is __get__()
__set__()
assigned a value, __delete__()
It is triggered when a property is deleted with Del
2, the role of descriptors
is a property that is used to proxy another class (the descriptor must be defined as a class property of the class and cannot be defined in the constructor)
Descriptors are defined in the class properties of another class, and descriptors are in the class property __dict__
dictionary of a class
Example 1
Class Foo: ? def __get__ (self, instance, owner): print ("performed __get__") ? def __set__ (self, instance, value): print ("__set__ executed") ? def __delete__ (self, Instance): print ("performed __delete__") ? ? Class Bar: x = Foo () ? def __init__ (self,name): self.name = name ? ? b = Bar ("Nick") b.x #调用执行描述符里的__get__方法 print (b.x) # b.x = 1 # Call the __set__ method that performs the description character print (b.__dict__) del b.x #调用执行描述符里的__delete__方法 print (b.__dict__)
Output results
Executed __get__ executed __get__ None executed __set__ {' name ': ' Nick '} executed __delete__ {' name ': ' Nick '}
Example 2
#描述符Str class Str:def __get__ (self, instance, owner): print (' St R call ') def __set__ (self, instance, value): Print (' str set ... ') def __delete__ (self, Instance): Print (' str delete ... ') ? #描述符Int class Int:def __get__ (self, instance, owner): print (' Int call ') def __set__ (self, instance, Valu E): print (' int set ... ') def __delete__ (self, Instance): print (' int delete ... ')? Class People:name=str () Age=int () def __init__ (self,name,age): #name被Str类代理, age is represented by Int class, Self.name =name self.age=age? #何地? : A class attribute defined as another class? #何时? : And see the following demos? P1=people (' Alex ', 18)? #描述符Str的使用 p1.name p1.name= ' Egon ' del p1.name? #描述符Int的使用 p1.age p1.age=18 del p1.age? #我们来瞅瞅到底发生了什么 print ("__p1.__dict__", p1.__dict__) print (people.__dict__)? #补充 print (Type (p1) = = people) #type (obj) is actually the print (type (p1) that looks at what class obj is instantiated from. __dict__ = = people.__dict__)
Output results
STR Settings ... int set ... STR calls str settings ... STR delete ... int calls int setting ... int delete ... __p1.__dict__ {} {' __module__ ': ' __main__ ', ' name ': <__main__. Str object at 0x021c6850>, ' age ': <__main__. Int object at 0x021c6870>, ' __init__ ': <function people.__init__ at 0x021c5db0>, ' __dict__ ': <attribute ' __di Ct__ ' of ' people ' objects>, ' __weakref__ ': <attribute ' __weakref__ ' of ' people ' objects>, ' __doc__ ': None} True
3, two types of descriptors
(1) Data descriptor: At least implemented __get__()
and __set__()
? Class Foo: def __set__ (self, instance, value): print (' Set ') def __get__ (self, instance, owner): Print (' Get ')
(2) Non-data descriptor: not implemented__set__()
Class Foo: def __get__ (self, instance, owner): print (' Get ')
Note: Non-data descriptors are generally only __get__, and if reserved __delete__ execution will be an error.
4. Precautions:
(1) The descriptor itself should be defined as a new class, and the class being represented should also be a new class (All of the new classes in Python3)
(2) A descriptor must be defined as a class property of another class and cannot be defined in a constructor.
(3) To strictly follow this priority, priority from high to the end is
A. Class properties B. Data descriptor c. Instance properties D. Non-data descriptor E. Property triggering __getattr__()
not found
Example 1
Class Foo: ? def __get__ (self, instance, owner): print ("performed __get__") ? def __set__ (self, instance, value): print ("__set__ executed") ? def __delete__ (self, Instance): print ("performed __delete__") ? class people: ? Name = Foo () ? def __init__ (self,name): self.name = name ? ? p = People ("Nick") people.name = "Nick" #调用执行了描述符的__set__方法, this step class attribute is defined by the previous descriptor as another string, # So the following call again will not be able to use the descriptor again people.name ? #可以得出结论, the precedence of class properties is greater than the data descriptor
Example 2
Class Foo: ? def __get__ (self, instance, owner): print ("performed __get__") ? def __set__ (self, instance, value): print ("__set__ executed") ? def __delete__ (self, Instance): print ("performed __delete__") ? class people: ? Name = Foo () ? def __init__ (self,name): self.name = name ? ? p = People ("Nick") #实例化对象, call the __set__ of the data descriptor, # But since the __set__ of the descriptor just performs the print operation, nothing is done, so the __dict__ of the P object is nothing P.name = "Nicholas" print (p.__dict__) #输出的结果为空 ? #因此可以得出结论, the precedence of the data descriptor is greater than the instance property (dictionary operation)
Example 3
Class Foo (object): def __init__ (self): pass ? def __get__ (self, instance, owner): print ("performed __get__") ? class people (object): ? Name = Foo ("x") ? def __init__ (self,name,age): self.name = name Self.age = Age ? ? ? p = People ("Nick") #实例化对象, here because the non-data descriptor, the priority is lower than the instance property, # So the instance property is set directly here, but no longer called the Descriptor Print (p.name) # Print Direct output Instance properties print (p.__dict__) #输出的结果: {' name ': ' Nick ', ' Age ': *} ? #因此可以得出结论, the precedence of instance properties is greater than non-data descriptors
Example 4
Class Foo (object): def __init__ (self,name2): self.name2 = name2 ? def __get__ (self, instance, owner): print ("performed __get__") ? ? class people (object): ? Name = Foo ("x") ? def __init__ (self,name,age): self.name = name Self.age = Age ? def __getattr__ (self, item): print ("__getattr__") ? ? p = People ("Nick") #实例化对象, here because the non-data descriptor, the priority is lower than the instance property, # So the instance property is set directly here, but no longer called the Descriptor Print (p.name) Print (p.sex) #调用不存在的属性执行了__getattr__ Print (p.__dict__) #输出的结果: {' name ': ' Nick ', ' age ': 18}
5, the application of descriptors
Example 1
Class Type:? def __init__ (self,key,expect_type): Self.key = key Self.expect_type = Expect_type? def __get__ (self, instance, owner): Print ("Execute __get__ Method") print (self) #这里的self就是type类的对象 Print (instance) #这里的instance就是传入的People类的对象 print ("Execute __get__ Method") return Instance.__d Ict__[self.key] #通过instance的字典获取对象的属性值? def __set__ (self, instance, value): Print ("Execute __set__ Method") Instance.__dict__[self.key] = value #instance Is the object of another class, where do you want to set the object's Dictionary of properties? def __delete__ (self, Instance): Print ("Execute __delete__ Method") Instance.__dict__.pop (Self.key) #删除对象的属性? Class People:name = Type ("name", str) age = Type ("Age", int)? def __init__ (self,name,age): self.name = name Self.age = age? P1 = People ("Nick") #调用2次描述符, set the dictionary for the object Print (p1.name) #通过数据描述符获取对象的属性值 print (p1.__dict__) p1.age = #调用描述符对对象进 Line Set Print (p1.__dict__)
Output results
Execute the __set__ method to execute the __set__ method to Execute the __get__ method <__main__. Type object at 0x004cb4f0> <__main__. People object at 0x02106df0> execution __get__ method Nick {' name ': ' Nick ', ' age ': ' execute __set__ method {' Name ': ' Nick ', ' Age ': 20}
?
Example 2
Class Type:? def __init__ (self,key,expect_type): Self.key = key Self.expect_type = Expect_type? def __get__ (self, instance, owner): Print ("Execute __get__ Method") print (self) #这里的self就是type类的对象 Print (instance) #这里的instance就是传入的People类的对象 print ("Execute __get__ Method") return Instance.__d Ict__[self.key] #通过instance的字典获取对象的属性值? def __set__ (self, instance, value): Print ("Execute __set__ Method") if not Isinstance (Value,self.expect_type): Print ("%s you entered is not%s"% (Self.key,self.expect_type)) raise TypeError Instance.__dict__[self.key] = value #instance是另一个类的对象, where do you want to set the property dictionary for the object? def __delete__ (self, Instance): Print ("Execute __delete__ Method") Instance.__dict__.pop (Self.key) #删除对象的属性? Class People:name = Type ("name", str) age = Type ("Age", int)? def __init__ (self,name,age): self.name = name Self.age = age? P1 = People ("Nick") #调用2次描述符, set the dictionary of the object to print (P1.name) #通过数据描述符获取对象的属性值 print (p1.__dict__) p1.age = #调用描述符对对象进行设 Print (p1.__dict__) # p1.name = one #通过描述符的if not isinstance (value,self.expect_type) determine the type of the property? # P2 = people (88,18) #通过描述符的if not isinstance (value,self.expect_type) determine the type of the property
iv.
__enter__
and
__exit__
The open file operation is operated with the with Open () as F, which is called the context Management Protocol, the WITH statement, in order for an object to be compatible with the WITH statement, __enter__
and __exit__
methods must be declared in the class of the object.
__enter__(self)
: Triggers the operation of this method when with starts running
__exit__(self, exc_type, exc_val, exc_tb)
: The run of this method is triggered when the with run ends
Exc_type If an exception is thrown, this gets the type of the exception
Exc_val If an exception is thrown, the exception content is displayed here
EXC_TB If an exception is thrown, this shows where
Use or Benefits:
1. The purpose of using the WITH statement is to put the code block in with, and with the end, the cleanup work is done automatically without manual intervention
2. In a programming environment where you need to manage resources such as files, network connections, and locks, __exit__
You can customize the mechanism for automatically releasing resources, and you don't have to deal with the problem.
Example
Class OPEN: def __init__ (self,name): self.name = name def __enter__ (self): print ("Execute __enter__") return self def __exit__ (self, exc_type, Exc_val, EXC_TB): print ("Execute __exit__") print (Exc_type) print (exc_val) print ( exc_tb) print ("Execute __exit__2222") with OPEN ("A.txt") as F: print (f) # Performs a print __enter__ built-in method, while printing the results returned by the built-in method #with the execution of the __exit__ method at the end of the statement, prints none without errors, prints the wrong message print ("Context Management Protocol")
The path to Python (27th) object-oriented advanced: Built-in methods, descriptors