Iteration, generation, decorator

Posted by scorphus on Sun, 02 Jan 2022 21:54:30 +0100

1. Descriptor (): assign the instance of a special type of class to the attribute of another class.
A descriptor is a property that assigns an instance of a particular type of class to another class
For special types of requirements, at least the following three methods shall be realized:
get(self, instance, owner)
Used to access a property, which returns the value of the property
set(self, instance, value)
It will be invoked in the attribute assignment operation without returning any content.
delete(self, instance)
Control the deletion operation and return nothing
Note: instance refers to the instance object of another class. owner refers to the class itself of another class. Value refers to the value of the instance object. (descriptor is a class, any class that implements at least three methods)

Add descriptive classes MyDecriptor,Assign to Test Properties of
>>> class MyDescriptor:
	def __get__(self, instance, owner):
		print("getting...", self, instance, owner)
	def __set__(self, instance, value):
		print("setting...", self, instance, value)
	def __delete__(self, instance):
		print("deleting...", self, instance)
>>> class Test:
	x = MyDescriptor()
>>> test = Test()
>>> test.x
getting... <__main__.MyDescriptor object at 0x0000000002FF0080> <__main__.Test object at 0x0000000002FACCC0> <class '__main__.Test'>
>>> test
<__main__.Test object at 0x0000000002FACCC0>
>>> test.x = 'fuck'
setting... <__main__.MyDescriptor object at 0x0000000002FF0080> <__main__.Test object at 0x0000000002FACCC0> fuck
>>> del test.x
deleting... <__main__.MyDescriptor object at 0x0000000002FF0080> <__main__.Test object at 0x0000000002FACCC0>

test.x This is the value taking operation, which uses“__get__"Function. Return values include MyDecriptor Class instance object, Test Instance object for test And the class to which it belongs.
test.x = 'lalala' Is an assignment operation, using“__set__"Function, the return value includes		MyDecriptor Class instance object, Test Instance object for test And the value assigned.

del test.x is the delete operation

You can also use methods of attribute types. Using property(), you can easily create available descriptors for any property. The syntax for creating property() is property(fget=None, fset=None, fdel=None, doc=None), where:
fget: property acquisition method fset: property setting method
fdel: attribute deletion method doc: docstring

class Person(object):
    def __init__(self):
        self._name = ''
 
    def fget(self):
        print ("Getting: %s" % self._name)
        return self._name
     
    def fset(self, value):
        print ("Setting: %s" % value)
        self._name = value.title()
 
    def fdel(self):
        print ("Deleting: %s" %self._name)
        del self._name
    name = property(fget, fset, fdel, "I'm the property.")


>>> p = Person()
>>> p.name = 'haha'
Setting: haha
>>> p.name
Getting: Haha
'Haha'
>>> del p.name
Deleting: Haha

Implement the property() function yourself

>>> class MyProperty:
	def __init__(self, fget=None, fset=None, fdel=None):
		self.fget = fget
		self.fset = fset
		self.fdel = fdel

	def __get__(self, instance, owner):
		return self.fget(instance)
	def __set__(self, instance, value):
		self.fset(instance, value)
	def __delete__(self, instance):
		self.fdel(instance)
		#The above code is the code of a descriptor class
>>> class C:
	def __init__(self):
		self._x = None
	def getX(self):
		return self._x
	def setX(self, value):
		self._x = value
	def delX(self):
		del self._x
	x = MyProperty(getX, setX, delX)
>>> c=C()
>>> c.x = 'fuck'
>>> c.x
'fuck'

2. Iterator
Iterators usually refer to sequences: string dictionary list tuples An iterator can be understood as a package of data

# Iteration of list
list = [12, 35, 67, 89]
for i in list:
    print(i, end=' ')
print("\n")
#Dictionary iteration
dict1 ={"lmf": "1", "cym": "2", "czh": "3"}
for i in dict1:         # Iterating is the key
    print(i, dict1[i])
12 35 67 89 

lmf 1
cym 2
czh 3

Built in functions for iterative operations:
iter() Gets the iterator of the container object
next() Returns the next value. If there is no next value, an exception will be thrown
str = "wlytlj"
a = iter(str)    # iter gets the iterator object and returns it to a
while True:
    try:
        i = next(a) 
    except StopIteration:  # No stopIteration exception will be thrown after next to catch the exception and end the loop
        break
    print(i)    
On the magic method of iteration
_ _ iter _ _() : Returns the iterator itself return self
_ _ next _ _() : Determines the iteration rules of the iterator
class Fib():
    def __init__(self, n= 10):
        self.a = 0
        self.b = 1
        self.n = n

    def __iter__(self):
        print("iter...")
        return self
    def __next__(self):
        print("next...", end=" ")
        self.a, self.b = self.b, self.a+self.b
        if self.a >self.n:
            raise StopIteration    # Throw exception

        return self.a

fib = Fib()
for i in fib:
   print(i)

iter...
next... 1
next... 1
next... 2
next... 3
next... 5
next... 8
next... 13
next... 

3. Producer
Generator is an iterative method, which can be implemented by adding a yield statement to an ordinary function
Imitate collaborative programs (collaborative programs: independent function calls that can be run. Functions can be suspended or suspended, and continue or restart where the program leaves when necessary)
Generator is a special function. The call can be interrupted or suspended, and a generator object is returned through yield.
The yield keyword can be understood as follows: when the function runs to this line, the program will pause here, yield is equivalent to return, and the next iteration will start from the next line of yield code.

	The iterator implementation relies on iteratable objects and does not necessarily use generator functions
	However, objects that use generator functions are iteratable

4. Derivation

#A number within the list derivation 40 that can be divided by 2 and cannot be divided by 3
list = [i for i in range(100) if not(i % 2) and (i % 3)]
print(list)

#The dictionary derivation is divided by 2 within 10
dic = {i : (i %2) == 0 for i in range(10)}
print(dic)

#Set derivation finds the number in a list that can be divided by 2 to form a set
myset = {i for i in [1,3,2,1,2,6,5,3,4,1,2,3] if (i % 2) == 0}

#Tuple generator derivation
tup = (i for i in range(10) if i%2)
print(tup)
print('\n', sum(i for i in range(10) if i % 2))   #Take the generator object as a function parameter
#Read generator
for i in tup:
    print(i, end=' ')

5. Decorator

Topics: Python