Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Functions of iterators, generators, and decorators in Python

2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article mainly explains "the functions of iterators, generators and decorators in Python". The content in the article is simple and clear, and it is easy to learn and understand. Please follow the editor's train of thought to study and learn the functions of iterators, generators and decorators in Python.

Iterator 1. Iterable object 1) iterable object definition

For iterators, we should be more familiar with iterable objects, which we have mentioned more or less before, both in source code and in lectures. In the past, in order to make it easier for you to understand iterable objects, the explanation may not be very correct, so today we will formally talk about what iterable objects are. Literally, let's disassemble it first: what is the object? Everything in Python is an object. A variable, a list, a string, a file handle, a function name, etc., can be called an object. In fact, an object is an instance, a real thing. So what is iteration? In fact, we often encounter the word iteration, update iteration and so on in our daily life. Iteration is a repetitive process, but it cannot be a simple repetition (if it is a simple repetition then it is no different from a cycle). Each repetition is based on the result of the previous one. For example, your father gave birth to you, you gave birth to your father, oh no, you gave birth to your son, your son gave birth to your grandson, etc., each generation is different; and you have used app, Wechat, Douyin, etc., and every once in a while will make some updates based on the last time, then this is iteration. An iterable object is literally a real thing that can be repeated.

So what are the iterable objects we analyzed literally just now, and what are the iterable objects we have come into contact with so far?

Str list tuple dic set range file handles, etc., so why can't int,bool be called iterable objects? Although these do not seem to match literally, we should have certain criteria or rules to judge whether the object is iterable or not.

In python, all objects that contain iter methods inside are iteratable objects.

2) View the internal methods of the object

What is the method inside the object? is there any other solution besides looking at the source code? Of course, you can use dir () to determine what method an object has.

S1 = 'alex'print (dir (S1))

Dir () returns a list of all the method names in the form of strings for the object. This allows us to determine whether an object in python is an iterable object:

S1 = 'alex'i = 100print (' _ iter__' in dir (I)) # Falseprint ('_ iter__' in dir (S1)) # True3) summary:

Literally: an iterable object is a real thing that can be repeated.

From a professional point of view: all objects that contain iter methods inside are iterable objects.

An iterable object can be judged by determining whether the object has a 'iter' method.

Advantages of iterable objects:

You can visually view the data inside.

Disadvantages of iterable objects:

1. Takes up memory.

two。 Iterable objects cannot be iterated with values (except for index, key).

Then some people question this shortcoming. Even if I throw away the index and key, I can take the value through the for loop. Yes, they can all be valued through the for loop. In fact, the for loop makes a small transformation at the bottom, that is, it first converts the iterable object into an iterator, and then takes the value. So next, let's take a look at what the iterator is.

two。 Iterator 1) definition of iterator

Literally, an iterator is a tool that can take values iteratively, and it is more appropriate to use it as a tool here.

Professionally, an iterator is an object that implements a parameterless next method, returns the next element in the sequence, or throws a StopIteration exception if there is no element. the iterator in python also implements the iter method, so the iterator can also iterate. From "fluent python"

So there is some advance in the above explanation, and it is difficult to understand, so let's put it simply: in python, an object that contains a 'Iter' method and a' next' method inside is an iterator.

2) how to determine whether the object is an iterator

Ok, so we have this definition, so we can determine whether some objects are iterators or iteratable objects, please judge these objects: which str list tuple dict set range file handle is an iterator and which is an iterable object:

O1 = 'alex'o2 = [1,2,3] o3 = (1,2,3) O4 = {' name': 'too white', 'age': 18} O5 = {1,2,3} f = open (' file',encoding='utf-8'') Mode='w') print ('_ iter__' in dir (o1)) # Trueprint ('_ iter__' in dir (O2)) # Trueprint ('_ iter__' in dir (o3)) # Trueprint ('_ iter__' in dir (o4)) # Trueprint ('_ iter__' in dir (o5)) # Trueprint ('_ iter__' in dir (f) # True# hsagnprint ('_ next__' in dir) (O1)) # Falseprint ('_ next__' in dir (O2)) # Falseprint ('_ next__' in dir (o3)) # Falseprint ('_ next__' in dir (o4)) # Falseprint ('_ next__' in dir (o5)) # Falseprint ('_ next__' in dir (f)) # Truef.close ()

As can be verified by the above code, of the objects we have learned before, only the file handle is an iterator, and the rest of the data types are iterable objects.

3) how to convert an iterable object into an iterator: L1 = [1, 2, 3, 4, 5, 6] obj = L1. Iterator _ () # or iter (L1) print (obj) # 4) iterator value:

Iterable objects cannot be iterated all the time (except for indexing, slicing, and Key), but they can be converted to iterators, which take values using next ():

L1 = [1,2,3,] obj = L1. Iterative iterators _ () # or iter (L1) # print (obj) # ret = obj.__next__ () print (ret) ret = obj.__next__ () # StopIterationprint (ret) # iterator uses next to take the value: a next takes the corresponding value If you run out of values in the iterator, and you still need next,#, then report an error in StopIteration. 5) while simulates the internal circulation mechanism of for:

As we just mentioned, the loop object of the for loop must be an iterable object, but this does not mean that the iterable object can be taken as a value, because the internal mechanism of the for loop is to convert the iterable object into an iterator, then use next to take the value, and finally use exception handling to handle the exception thrown by StopIteration.

L1 = [1, 2, 3, 4, 5, 6] # 1 converts the iterable object into an iterator obj = iter (L1) # 2, uses while loop and next to take the value while 1: # 3, and uses exception handling to terminate the loop try: print (next (obj)) except StopIteration: break6 summary:

Literally: an iterator is a tool that can iterate for values.

Professionally speaking: in python, objects that contain 'Iter'' methods inside and contain 'next'' methods are iterators.

Advantages of iterators:

Save memory.

The iterator takes up only one piece of data in memory: because the last piece of data is released in memory each time a value is taken, the current piece of data is loaded.

Inert mechanism.

Next one value at a time, never too many values.

There is an iterator pattern that can well explain the above two: iteration is the cornerstone of data processing. When scanning data sets that can't fit in memory, we need to find a lazy way to get data items, that is, one data item at a time as needed. This is the iterator pattern.

Disadvantages of iterators:

Can not visually view the data inside.

When taking a value, you don't go back, you can only take the value down all the time.

L1 = [1,2,3,4,5,6] obj = iter (L1) for i in range (2): print (next (obj)) for i in range (2): print (next (obj)) 3. Comparison between iterable objects and iterators

Today we have a more in-depth understanding of iterable objects and iterators, and then let's talk about the comparison and application between the two:

Iterable objects:

Is a private method is more flexible (such as lists, dictionary additions, deletions and queries, common string operations, etc.), more intuitive, but memory-intensive, and can not directly iterate through the loop to get the value of such a data set.

Application: when you focus on flexible processing of data and sufficient memory space, setting the dataset as an iterable object is a clear choice.

Iterator:

Is a very memory-saving, can record the location of the value, can be directly through the loop + next method to take the value, but not intuitive, the operation method is relatively single data set.

Application: when your data is large enough to burst your memory or when you choose to save memory as your preferred factor, setting the dataset as an iterator is a good choice. (see why python sets the file handle to an iterator.)

Generator 1.1 first acquaintance with the generator

What is a generator? This concept is relatively vague, all kinds of literature have different understandings, but the core is basically the same. The essence of a generator is an iterator, and most of the time in the python community, iterators and generators are treated as the same concept. Isn't it the same? Why create a generator? Generators and iterators are also different, the only difference is that iterators are written tools provided to you by Python or converted from data (such as file handle, iter). Generators are tools that need to be built with our own python code. That's the biggest difference.

1.2 how the generator is built

There are three ways to create a generator in python:

Through the generator function

Derivation through generator

Python built-in functions or modules provide (in fact, 1Magne3 is essentially similar, both are generated in the form of functions, except that 1 is a generator function written by itself, and 3 is a generator function provided by python)

1.3 Generator function

Let's first look at building generators through generator functions.

First, let's look at a very simple function:

Def func (): print (11) return 22ret = func () print (ret) # result: 1122

Replace the return in the function with yield, so that func is not a function, but a generator function

Def func (): print (11) yield 22

There is no change in our writing like this. Why? Let's take a look at what we get by adding parentheses to the function name.

Def func (): print (11) yield 22ret = func () print (ret) # run result:

The result of the operation is different from the top one. Why? Because there is a yield in the function, the function is a generator function.

When we execute this function. It is no longer the execution of a function. Instead, you get the generator object, so how do you get the value of the generator object?

As we said before, the essence of a generator is an iterator. The generator takes the value as the iterator takes the value. So we can execute next () directly to execute the following generator

Def func (): print ("111") yield 222gener = func () # the function does not persist at this time. It is only when you get the generator ret = gener.__next__ () # that the function will execute print (ret) # and yield will give the data produced by func to ret. Results: 111222

And I can write multiple yield in my generator function.

Def func (): print ("111") yield 222print (" 333 ") yield 444gener = func () ret = gener.__next__ () print (ret) ret2 = gener.__next__ () print (ret2) ret3 = gener.__next__ () # the last yield is completed. Again, _ _ next__ () program reported an error print (ret3) result: 111222333444

When the program runs the last yield, then continuing to run the next () program will report an error, and if a yield corresponds to a next,next exceeding the number of yield, it will report an error, just like an iterator.

The difference between yield and return:

Return generally sets only one in the function, and its function is to terminate the function and return a value to the executor of the function.

Yield can set more than one in the generator function, he will not terminate the function, next will get the corresponding yield generated elements.

For example:

Let's take a look at this demand: the old boy ordered 10000 steamed buns from the boss who sold steamed buns downstairs. The owner of the steamed stuffed bun shop was so practical that he made it all at once.

Def eat (): lst = [] for i in range (1m 10000): lst.append ('steamed stuffed bun' + str (I)) return lste = eat () print (e)

There is no problem with this, but because we do not have so many students, we only eat about 2000, and the remaining 8000 can only take up a certain amount of space and put it aside. If the steamed stuffed bun shop owner is efficient enough, I eat a steamed stuffed bun, you make a steamed stuffed bun, then this will not take up too much space for storage, perfect.

Def eat (): for i in range (110000): yield 'steamed stuffed bun' + str (I) e = eat () for i in range: next (e)

The difference between the two:

The first is to directly make all the steamed buns and take up memory.

The second is to eat one at a time and produce one, which saves a lot of memory and retains the location of the last time.

Def eat (): for i in range (110000): yield 'steamed buns' + str (I) e = eat () for i in range: next (e) for i in range (300): next (e) # the numbers of multiple next buns are recorded in order. 1.4 send method

Next, let's learn about a new thing, the send method.

# next can only get values generated by yield, but cannot pass values. Def gen (name): print (f'{name} ready to eat') while 1: food = yield print (f'{name} start to eat {food}') dog = gen ('alex') next (dog) # and it is possible to use send. Def gen (name): print (f'{name} ready to eat') while 1: food = yield 222print (f'{name} start to eat {food}') dog = gen ('alex') next (dog) # the first time you must use next to keep the pointer behind the first yield # same as next You can get the value of yield ret = dog.send ('bone') print (ret) def gen (name): print (f'{name} ready to eat') while 1: food = yield print (f'{name} start to eat {food}') dog = gen ('alex') next (dog) # and send the last yield value dog.send (' bone') dog.send ('dog food') dog.send ('sausage')

The difference between send and next ():

Similarities:

Both send and next () can have the corresponding yield of the generator execute down once.

You can get the values generated by yield.

Differences:

The first time you get the yield value, you can only use next, not send (you can use send (None)).

Send can pass a value to the previous yield.

1.4 yield from

Provide a method in python3 that can directly return each data in an iterable object as a result of the generator

# compare yield with yield from def func (): lst = ['Weilong', 'old popsicle', 'Arctic Ocean', 'beef and sheep match'] yield lstg = func () print (g) print (next (g)) # just return a list def func (): lst = ['Weilong', 'old popsicle', 'Arctic Ocean' Yield from lstg = func () print (g) # he will return each element of the iterable object (list) as each result of the iterator. Print (next (g)) 'yield from [' Weilong', 'Old Popsicle', 'Arctic Ocean', 'cattle and Sheep match'] is equivalent to: yield 'Weilong' yield 'Old Popsicle' yield 'Arctic Ocean' yield 'cattle and Sheep match''

There is a small pit where yield from returns every element in the list, so writing two yield from will not have an alternating effect.

Def func (): lst1 = ['Weilong', 'old popsicle', 'Arctic Ocean', 'cattle and sheep match'] lst2 = ['steamed bread', 'twistbread', 'bean buns', 'big cake'] yield from lst1 yield from lst2g = func () for i in g: print (I) decorator 1. Open and closed principle

What is the principle of opening and closing? Some students ask "open" and "closed". These are two antonyms. Can this still constitute a principle? Isn't that contradictory? Actually, it's not contradictory. The principle of openness and closure is discussed on a case-by-case basis.

Once our software is launched (for example, your software is mainly composed of multiple functions), then the software should be open to the expansion of functions, such as your game has been iteratively updated to introduce new ways of playing and new functions. But changes to the source code are closed. You take a function as an example. If there is a function that dodges in your game source code, then your function must be called in many places, for example, the other party throws mines, the other side shoots, and the other party uses a knife. You will call your dodge function, so if your dodge function source code has changed, or the calling mode has changed, when the other party initiates the corresponding action, you are calling your dodge function. There will be problems. Therefore, the specific definition of the principle of openness and closure is as follows:

1. Is open to expansion

We say that it is impossible for any program to think of all the functions at the beginning of its design and not to make any updates or modifications in the future. So we have to allow the code to expand and add new features.

two。 Closed for modification

As we just mentioned, because a function we wrote is likely to have been delivered to other people, if we modify the interior of the function or change the way the function is called, it is likely to affect other users who are already using the function. OK, after understanding the closure principle of Kaifeng, let's talk about decorators.

What is a decorator? From the literal meaning, first talk about decoration, what is decoration? Decoration is to add new ones, such as the house you just bought. The next step is to design, decorate, decorate, floor, wall, home appliances and so on in the way you like. What is a device? The device is not only a tool, but also a function, and the decorator is easy to understand: it is to add new functions.

For example, if I can't fly now, how can I fly? Add me a wing and I can fly. So if you give me a wing, will it change my original behavior? My previous lifestyle such as eating, drinking, sleeping and so on will not change. It just adds a new function to my original foundation.

The decorator (decoration, wings) we are talking about today is function-oriented, which is a function.

The object to be decorated: such as the semifinished house, myself, is actually a function. 0

So the ultimate perfect definition of a decorator is to add additional functionality to it without changing the source code of the original decorated function and how it is called.

two。 First acquaintance with decorator

Next, let's use an example to explain this decorator:

Requirements description: you are now working in the development department of xx Technology Co., Ltd., and the leader gives you a business requirement for you to complete: let you write code to test the execution efficiency of functions written by little ming.

Def index (): print ('Welcome to the blog Park home page')

Version 1:

Requirements analysis: what should you do if you want to test the execution efficiency of this function? You should record a time before and after the execution of this function, and this time difference is the execution efficiency of this function. So how do you get the execution time? You can take advantage of the time module and have a time.time () function.

Import timeprint (time.time ())

This method returns GMT, the number of seconds between now and 00:00:00 on January 1, 1970. Also known as time stamp, he is always changing. So to calculate the execution efficiency of shopping_car is to calculate the time of the timestamp before and after execution, and then calculate the difference.

Import timedef index (): print ('Welcome to the blog Park home page') start_time = time.time () index () end_time = time.time () print (f 'the efficiency of this function is {end_time-start_time}')

Because the index function has only one line of code, the execution efficiency is too fast, so we use a sleep of the time module to simulate it.

Import timedef index (): time.sleep (2) # simulate network latency and code efficiency print ('Welcome to the blog Park home page') start_time = time.time () index () end_time = time.time () print (f 'this function is {end_time-start_time}')

Version 1 analysis: you have completed this requirement now, but is there any problem? Although you have only written four lines of code, what you have completed is a function that tests the execution efficiency of other functions. What if you test the function efficiency of Xiao Zhang, Xiao Li and Xiao Liu? Do you have to copy it all:

Import timedef index (): time.sleep (2) # simulate network delay and code efficiency print ('Welcome to blog Park homepage') def home (name): time.sleep (3) # simulate network delay and code efficiency print (f 'welcome to {name} home page') start_time = time.time () index () end_time = time.time () print ( The execution efficiency of this function is {end_time-start_time}') start_time = time.time () home ('too white') end_time = time.time () print (the execution efficiency of this function is {end_time-start_time}').

There is too much repetitive code, so what do you do to solve the problem of duplicated code? Have we learned about functions? functions are function-oriented, reducing repetitive code, so that we can continue to rectify them.

Version 2:

Import timedef index (): time.sleep (2) # simulate network latency and code efficiency print ('Welcome to the blog Park home page') def inner (): start_time = time.time () index () end_time = time.time () print (f 'this function executes {end_time-start_time}') inner ()

But it is also a problem for you to write this way. Although you encapsulate the code for testing functions into a function, you can only test the function index of the little ming classmate. What if you test the functions of other colleagues? What do you do?

Import timedef index (): time.sleep (2) # simulate network latency and code efficiency print ('Welcome to the blog Park home page') def home (name): time.sleep (3) # simulate network latency and code efficiency print (f 'welcome to {name} home page') def inner (): start_time = time.time () index () Home ('too white') end_time = time.time () print (f 'the efficiency of this function is {end_time-start_time}') timer ()

If you do what you did above, isn't it too low to manually change the code of other colleagues every time you test it? So how do you test other functions dynamically? Have we learned about passing parameters of functions? Can you pass the function name of the decorated function as an argument to the function?

Version 3:

Import timedef index (): time.sleep (2) # simulate network latency and code efficiency print ('Welcome to the blog Park home page') def home (name): time.sleep (3) # simulate network latency and code efficiency print (f 'welcome to {name} home page') def timmer (func): # func = = index function start_time = time.time ( ) func () # index () end_time = time.time () print (f 'the execution efficiency of this function is {end_time-start_time}') timmer (index)

In this way, I pass the function name of the index function as an argument to the timmer function, and then execute the index function in the timmer function, which becomes a dynamic parameter. OK, now you will quickly practice the code of version 3. After the practice, do you find any problems? In contrast to the open and closed principle, first of all, the index function not only completes its previous function, but also adds a function to test execution efficiency, right? So it is also in line with the principle of openness. Secondly, has the source code of the index function changed? No, but the mode of implementation has changed, so it does not conform to the principle of closure. How to implement it originally? How does index () execute now? Inner (index), what is the problem with this? If index is called 100 times in your project, then I have to change the corresponding 100 calls to inner (index). It is very troublesome and does not conform to the principle of openness and closeness.

Version 4: implement the true open and closed principle: decorator.

This is also very simple, that is, the closure we talked about yesterday, as long as you sort out the execution process of that closure, then you don't think it will be difficult.

Import time def index (): time.sleep (2) # simulate network latency and code efficiency print ('Welcome to the blog Park home page') def home (name): time.sleep (3) # simulate network latency and code efficiency print (f' Welcome to {name} home page')

You put the above inner function on the outermost function timer, and then take the inner function name inside as the return value of the outermost function, so the simple decorator is written without any new knowledge, if not, you have to copy it several times and then understand the code.

Def timer (func): # func = index def inner (): start_time = time.time () func () end_time = time.time () print (f 'the execution efficiency of this function is {end_time-start_time}') return inner# f = timer (index) # f ()

Let's analyze the code, code execution to this line: F = timer (index) who executes first? Seeing an equal sign to the right of the equal sign, timer (index) executes the timer function to pass the name of the index function to the func parameter. Does the inner function inner execute? If not executed, the inner function returns the f variable. So executing f () is equivalent to executing the inner closure function. F (), which not only tests the efficiency but also executes the original function, is there a problem? Of course there is! Version 4 you want to solve the problem that the execution mode of the original function does not change, what to do? So you can change f to index variable and it's perfect! Index = timer (index) index () takes the students to run this process again, especially to note that the index outside the function is actually the memory address of the inner function rather than the index function. Let the students copy it and understand that this timer is the simplest version of the decorator, which adds additional functions to test the execution efficiency without changing the source code of the original index function and the way it is called.

3. Decorator with return value

You are now this code, completed the original version of the decorator, but still not perfect, because your decorated function index may have a return value, if there is a return value, your decorator should not affect the open and closed principle. But now you set it up and try it:

Import timedef index (): time.sleep (2) # simulate the network delay and the efficiency of the code print ('Welcome to the blog Park home page') return 'successful access' def timer (func): # func = index def inner (): start_time = time.time () func () end_time = time.time () print (f') the implementation of this function Line efficiency is {end_time-start_time}') return innerindex = timer (index) print (index ()) # None

After adding the decorator, his return value is None. Why? Because your current index is not the function name index, this index is actually the inner function name. So index () equates to inner () to whom your 'access success' return value should be returned? It should be returned to index so that it is open and closed, and to whom is it actually returned? It's actually returned to func, so you need to change your decorator code to return it to the outer index function name. So: here's what you should do:

Def timer (func): # func = index def inner (): start_time = time.time () ret = func () end_time = time.time () print (f 'the efficiency of this function is {end_time-start_time}') return ret return innerindex = timer (index) # innerprint (index ()) # print (inner ())

With the help of the inner function inner, you return the return value of func to the caller of the inner function, that is, the index outside the function, which implements the open and closed principle, and the index returns the value, which is indeed returned to 'index'.

Let the students practice.

4 decorated function decorator with parameters

So far, your decorated function still has no parameters? According to our open and closed principle, whether you add a decorator or not will not affect the use of your decorated function. So let's take a look.

Import timedef index (): time.sleep (2) # simulate network latency and code efficiency print ('Welcome to the blog Park home page') return 'successful access' def home (name): time.sleep (3) # simulate network latency and code efficiency print (f' welcome to {name} home page') def timer (func): # func = index def inner (): start_time = time.time () func () end_time = time.time () print (the execution efficiency of this function is {end_time-start_time}') what does return inner# want to timer decorate the home function to do? Home = timer (home) home ('too white')

If you do that above, it is obviously wrong. Why? Who is your home variable? It's inner,home ('too white') is actually inner ('too white'), but to whom should your argument 'too white' be passed? It should be passed to the home function, but to who actually? It's actually passed to inner, so we need to change the decorator's code to pass the argument 'too white' to home.

Import timedef index (): time.sleep (2) # simulate network latency and code efficiency print ('Welcome to the blog Park home page') return 'successful access' def home (name): time.sleep (3) # simulate network latency and code efficiency print (f' welcome to {name} home page') def timer (func): # func = home def inner (name): start_time = time.time () func (name) # home (name) = home ('too white') end_time = time.time () print (the execution efficiency of this function is {end_time-start_time}') what does return inner# want timer to decorate the home function to do? Home = timer (home) home ('too white')

So you realize, there is a small problem, now the formal parameter of the decorated function only has one parameter, what if there are more than one parameter? Some people say I will write as many as not on the line, that can not ah, you this decorator can decorate N different functions, the parameters of these functions are not uniform. So you have to have a parameter that can accept indefinite parameters to accept them. In this way, you have to think of * args,**kwargs.

Import timedef index (): time.sleep (2) # simulate network latency and code efficiency print ('Welcome to the blog Park home page') return 'successful access' def home (name,age): time.sleep (3) # simulate network latency and code efficiency print (name Age) print (f' Welcome to the {name} home page') def timer (func): # func = home def inner (* args,**kwargs): # function definition * stands for aggregation: so when your args = ('too white', 18) start_time = time.time () func (* args,**kwargs) # function executes * stands for breaking up: so * args-- > * ('too white', 18)-- > func ('too white', 18) end_time = time.time () print (f 'this function performs with {end_time-start_time}') return innerhome = timer (home) home ('too white', 18)

In this way, using the principle of fragmentation and aggregation of *, these arguments are perfectly passed to the corresponding parameters through the middle of the inner function.

Okay, type the above code again.

5. Standard edition decorator

Code optimization: syntax sugar

According to my study, we know that if you want to add a decorator to a function, it should be like this:

Def home (name,age): time.sleep (3) # simulate network latency and code efficiency print (name,age) print (f' Welcome to {name} homepage') def timer (func): # func = home def inner (* args,**kwargs): start_time = time.time () func (* args) * * kwargs) end_time = time.time () print (f 'the execution efficiency of this function is {end_time-start_time}') return innerhome = timer (home) home ('too white', 18)

If you want to add a decorator to home, you should write a sentence before each execution of home: home = timer (home) so that you actually add extra functionality to the home function home ('too white', 18). But it is also troublesome to write this sentence every time. So, Python provides us with a simplified mechanism to replace this sentence with a very simple symbol.

Def timer (func): # func = home def inner (* args,**kwargs): start_time = time.time () func (* args,**kwargs) end_time = time.time () print (f 'the efficiency of this function is {end_time-start_time}') return inner@timer # home = timer (home) def home (name Age): time.sleep (3) # simulates network latency and code efficiency print (name,age) print (f' Welcome to {name} homepage') home ('too white', 18)

You see, I adjusted the position at this time. If you don't put the decorator on it, timer won't be able to find it. Home function if you want to add a decorator, then you add @ home to the home function, which is equivalent to the sentence home = timer (home). There is no special meaning to do this, but to make it more simple. for example, you have seen the battle of the field army in movies, because it is not convenient to talk, use some simple gestures to represent some words, this is the meaning.

So far, the standard version of the decorator looks like this:

Def wrapper (func): def inner (* args,**kwargs):''perform the operation before the decorated function' ret = func 'perform the operation after the decorated function' 'return ret return inner

This is the standard decorator, fully in line with the principle of open and closed code. These lines of code must be memorized and can be used.

At this point, we need to use this decorator to complete a requirement: a simple version of simulated blog park login. At this time, take the students to take a look at the blog park and talk about the requirements: there are several pages after logging in to the blog park, diary,comment,home. If I want to visit these pages, I must verify that I have logged in. If I have successfully logged in, then I can access all these pages without resistance. If you are not logged in, none of the pages can be accessed. I must log in first, and only after the login is successful can I access this page. We use the successful execution of the function simulation as a successful access to this page, now write three functions, write a decorator, to achieve the above functions.

Def auth (): passdef diary (): print ('Welcome to the Diary Page') def comment (): print ('Welcome to the comments Page') def home (): print ('Welcome to the blog Park homepage') answer: login_status = {'username': None,' status': False,} def auth (func): def inner (* args * * kwargs): if login_status ['status']: ret = func () return ret username = input (' Please enter user name:'). Strip () password = input ('Please enter password:'). Strip () if username = = 'too white' and password = = '123': login_status ['status'] = True ret = func () return ret return inner@authdef diary (): print ('Welcome to the Diary Page') @ authdef comment (): print ('Welcome to the comments Page') @ authdef home (): print ('Welcome to the blog Park homepage') diary () comment () home () 6. Decorator with parameters

We see that the decorator is actually a closure function, and to put it simply, it is a two-layer function. Then it is a function, so it should have the function of passing parameters.

Login_status = {'username': None,' status': False,} def auth (func): def inner (* args * * kwargs): if login_status ['status']: ret = func () return ret username = input (' Please enter user name:'). Strip () password = input ('Please enter password:'). Strip () if username = = 'too white' and password = = '123': login_status ['status'] = True ret = func () return ret return inner

Look at the decorator on top of me, don't open it, it can't be on the first floor:

Def auth (x): def auth3 (func): def inner (* args * * kwargs): if login_status ['status']: ret = func () return ret username = input (' Please enter user name:'). Strip () password = input ('Please enter password:'). Strip () if username = = 'too white' and password = = '123 white: login_ Status ['status'] = True ret = func () return ret return inner return auth

Example: Douyin: binding is the Wechat account password. Mantis shrimp: what is bound is the account password of qq. What you need to complete now is that your decorator should judge the account and password on a case-by-case basis. Different functions use different accounts and passwords from different sources. But the decorator you wrote earlier can only accept one parameter, that is, the function name, so you write a decorator that accepts parameters.

Def auth3 (func): def inner (* args) * * kwargs): if login_status ['status']: ret = func () return ret if Wechat: username = input (' Please enter user name:'). Strip () password = input ('Please enter password:'). Strip () if username = = 'too white' and password = = '123': Login_status ['status'] = True ret = func () return ret elif' qq': username = input ('Please enter user name:'). Strip () password = input ('Please enter password:'). Strip () if username = = 'too white' and password = = '123 white: login_status [ 'status'] = True ret = func () return ret return inner@auth3def jitter (): print (' record the good life') @ auth3def pipefish (): print ('look forward to your inner divine comments')

Solution:

Def auth (x): def auth3 (func): def inner (* args * * kwargs): if login_status ['status']: ret = func () return ret if x = =' wechat': username = input ('Please enter user name:'). Strip () password = input ('Please enter password:'). Strip () if username = =' Too white 'and password = =' 123 and password: login_status ['status'] = True ret = func () return ret elif x = =' qq': username = input ('Please enter user name:'). Strip () password = input ('Please enter password:'). Strip () If username = 'too white' and password = '123 white: login_status [' status'] = True ret = func () return ret return inner return auth3@auth ('wechat') def jitter (): print (' record the good life') @ auth ('qq') def pipefish (): print (' look forward to Log_dic = {"flag": False} def auth (argv): def wraaper (func): def inner (* args) * * kwargs): if log_dic ["flag"]: func (* args * * kwargs) elif argv = = "QQ": print ("Welcome") user = input ("username:") pwd = input ("password:") if user = = "rsx" and pwd = = "rsx123": log_dic ["flag"] = True Func (* args * * kwargs) else: print ("wrong username and password") elif argv = = "wechat": print ("Welcome to login") user = input ("username:") pwd = input ("password:") If user = "rsx" and pwd = = "rsx123": log_dic ["username"] = user func (* args * * kwargs) else: print ("wrong username and password") else: print ("Please select APP login") return inner return wraaper# msg= "" # QQ# wechat# Please select: # "" # chose = input (msg). Upper () "@ auth ( "QQ") def foo (): print ("Tencent Foo () "# wraaper = auth (" QQ ") # foo = wraaper (foo) # foo ()" @ auth ("wechat") def foo (): print ("Wechat") foo () "" # wraaper = auth ("wechat") # foo = wraaper (foo) # foo () multiple decorators decorate a function def wrapper1 (func): def inner1 (* args,**kwargs): print (1) func (* args) * * kwargs) print (11) return inner1def wrapper2 (func): def inner2 (* args,**kwargs): print (2) func (* args,**kwargs) print (22) return inner2def wrapper3 (func): def inner3 (* args,**kwargs): print (3) func (* args) * * kwargs) print (33) return inner3@wrapper3@wrapper2@wrapper1def fo (): print (8) foo () Thank you for your reading The above is the content of "functions of iterators, generators and decorators in Python". After the study of this article, I believe you have a deeper understanding of the functions of iterators, generators and decorators in Python, and the specific use needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report