In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-25 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
What are the two suggestions of the Python writing cycle? to solve this problem, this article introduces the corresponding analysis and solution in detail, hoping to help more partners who want to solve this problem to find a simpler and easier way.
Python Learning tutorial (Python Learning Route): gives you a summary of two suggestions for Python writing cycles
Loop is a commonly used program control structure. We often say that one of the greatest advantages of machines over human beings is that machines can do something over and over again, but people can't. On the other hand, "loop" is the key concept to make the machine work repeatedly.
In terms of circular grammar, Python is both traditional and untraditional. Although it abandons the common for (init;condition;incrment) three-segment structure, it still chooses the two classic keywords for and while to express the loop. In most cases, our cycling needs can be met with forin, while while uses less.
Although the syntax of the loop is simple, it is not easy to write it well. Here, we will explore what is "authentic" loop code and how to write them.
What is the cycle of "tunnel"?
The word "authentic" is usually used to describe someone who does something very well and conforms to the local tradition. For example, when you go to a party of friends, your deskmate has a Cantonese. As soon as the other person opens his mouth, every sentence is a standard Beijing accent and a perfect accent. Then you can say to her, "your Beijing dialect is authentic."
Since the word "authentic" often describes real things such as accent and taste of cooking, what does the loop code of "authentic" mean? Let me take a classic example to explain.
If you ask someone who has been studying Python for a month, "how do I get the current subscript while traversing a list?" . He might hand over the code like this:
Index = 0for name in names: print (index, name) index + = 1
Although the above loop is correct, it is not authentic at all. A person with three years of Python development experience would say that the code should be written like this:
For I, name in enumerate (names): print (I, name)
Enumerate () is a built-in function of Python that takes an "iterable" object as a parameter and returns a new iterable object that is constantly generated (current subscript, current element). It is the most suitable for this scene.
So, in the above example, we would think that the second loop code is more "authentic" than the first.
Because it gets the job done smarter with more intuitive code.
Programming ideas represented by enumerate ()
However, judging whether a piece of loop code is authentic is not just based on knowing or not knowing a built-in method. We can dig deeper from the above example.
As you can see, Python's for loop has only one structure, forin, and the first half of the structure-assigning values to item- does not have many tricks to play with. So the iterable object in the second half is the only thing we can make a fuss about. The "decorating function" represented by the enumerate () function just provides a way to optimize the loop itself by modifying iterable objects.
Here I would like to give you my first suggestion:
Suggestion 1: use functions to modify the iterated object to optimize the loop
Using decorated functions to deal with iterable objects can affect circular code in a variety of ways. You don't have to go too far to find the right example to demonstrate this approach, and the built-in module itertools is an excellent example.
In a nutshell, itertools is a set of tool functions that contain many iterable object-oriented tools. I mentioned it in the previous series of articles, "the doorway of containers."
If you want to learn itertools, then the Python official documentation is your first choice, which has very detailed module-related information. But in this article, the emphasis will be slightly different from the official documentation. I will explain in detail how it improves the circular code through some common code scenarios.
1. Flattening multilayer nested loops with product
Although we all know that "flat code is better than nested code". But sometimes it seems necessary to write a multi-layer nested loop for a certain type of demand. For example, the following paragraph:
Def find_twelve (num_list1, num_list2, num_list3): "" from the list of three numbers, look for the existence and three numbers of 12 "" for num1 in num_list1: for num2 in num_list2: for num3 in num_list3: if num1 + num2 + num3 = = 12: return num1, num2, num3.
For this kind of multi-layer loop code that needs to be nested and iterate through multiple objects, we can use the product () function to optimize it. Product () can take multiple iterable objects and generate results continuously based on their Cartesian product.
From itertools import productdef find_twelve_v2 (num_list1, num_list2, num_list3): for num1, num2, num3 in product (num_list1, num_list2, num_list3): if num1 + num2 + num3 = = 12: return num1, num2, num3
Compared to the previous code, the function using product () completes the task with only one layer of for loop, and the code becomes more refined.
two。 Using islice to realize interlacing in loops
There is an external data file containing the title of the Reddit post, and the content format is as follows:
Python-guide: Python best practices guidebook, written for humans.---Python 2 Death Clock---Run any Python Script with an Alexa Voice Command
Perhaps for the sake of beauty, there is a "-" separator between every two headings in this document. Now, we need to get a list of all the headings in the file, so we have to skip these meaningless delimiters while traversing the contents of the file.
Referring to the previous understanding of the enumerate () function, we can do this by adding an if judgment based on the current loop sequence number to the loop:
Def parse_titles (filename): "" read the reddit topic name from an interlaced data file "with open (filename,'r') as fp: for I, line in enumerate (fp): # Skip the meaningless'--'delimiter if I% 2 = = 0: yield line.strip ()
But for this type of requirement for interlacing within a loop, using the islice () function in itertools to modify the looped object can make the loop body code simpler and straightforward.
The islice (seq,start,end,step) function has almost exactly the same parameters as the array slicing operation (list [start:stop:step]). If interlacing is required within the loop, simply set the third progressive length parameter step to 2 (the default is 1).
From itertools import islicedef parse_titles_v2 (filename): with open (filename,'r') as fp: # set step=2, skip the meaningless'--'delimiter for line in islice (fp, 0, None, 2): yield line.strip ()
3. Use takewhile instead of break statement
Sometimes we need to determine whether the loop needs to end early at the beginning of each loop. Such as the following:
For user in users: # when the first unqualified user appears, no later processing is carried out if not is_qualified (user): break # to process.
For this type of loop that needs to be interrupted in advance, we can use the takewhile () function to simplify it. Takewhile (predicate,iterable) constantly calls the predicate function with the current object as a parameter during the iteration of iterable and tests the return result. If the function returns a true value, the current object is generated and the loop continues. Otherwise, the current loop is interrupted immediately.
Sample code that uses takewhile:
From itertools import takewhilefor user in takewhile (is_qualified, users): # for processing.
There are some other interesting utility functions in itertools that can be used with loops, such as flattening double-layer nested loops with the chain function, iterating through multiple objects at the same time using the zip_longest function, and so on.
Space is limited, so I will not introduce them one by one here. If you are interested, you can go to the official documents for details.
4. Use the generator to write your own decorating function
In addition to the functions provided by itertools, we can easily use the generator to define our own loop modifier functions.
Let's take a simple function as an example:
Def sum_even_only (numbers): "summation of all even numbers in numbers" result = 0 for num in numbers: if num% 2 = = 0: result + = num return result
In the above function, in order to filter out all odd numbers in the loop, an additional if judgment statement is introduced. If we want to simplify the contents of the loop body, we can define a generator function that specializes in even filtering:
Def even_only (numbers): for num in numbers: if num% 2 = = 0: yield numdef sum_even_only_v2 (numbers): "summation of all even numbers in numbers" result = 0 for num in even_only (numbers): result + = num return result
After decorating the numbers variable with the even_only function, the interior of the sum_even_only_v2 function does not have to pay attention to the "even filtering" logic, but simply completes the sum.
Hint: of course, the above function is not practical. In the real world, this simple requirement is best done directly with generator / list expressions: sum (numfornuminnumbersifnum%2==0)
Recommendation 2: disassemble the complex code blocks in the loop according to their duties
I have always thought that a loop is a magical thing. Every time you write a new loop code block, it is like opening up a dark magic array, and everything in the array will start to be repeated endlessly.
But I also found that apart from the benefits of this dark magic array, it will also tempt you to keep stuffing more and more code into the array, including filtering out invalid elements, preprocessing data, printing logs, and so on. Even some content that does not belong to the same abstraction will be crammed into the same dark magic array.
You may take it for granted that we are in urgent need of the magic effect in the squad. If you don't stuff this pile of logic into the loop, where else can you put it?
Let's take a look at the following business scenario. On the site, there is a periodic script that executes every 30 days, and its task is to query users who have logged in at a specific time every weekend in the past 30 days, and then send them reward points.
The code is as follows:
Import timeimport datetimedef award_active_users_in_last_30days (): "get all users who have logged in from 8 p.m. to 10:00 over the past 30 weekends. Send it reward points "" days= 30 for days_delta in range (days): dt = datetime.date.today ()-datetime.timedelta (days=days_delta) # 5: Saturday, 6: Sunday if dt.weekday () not in (5,6): continue time_start = datetime.datetime (dt.year, dt.month, dt.day, 20,0) time_end = datetime.datetime (dt.year, dt.month, dt.day, 23,0) # convert to unix timestamp The subsequent ORM query needs ts_start = time.mktime (time_start.timetuple ()) ts_end = time.mktime (time_end.timetuple ()) # query users and send 1000 reward points for record in LoginRecord.filter_by_range (ts_start, ts_end): # here you can add complex logic send_awarding_points (record.user_id, 1000)
The above function is mainly composed of two layers of loops. The main responsibility of the outer loop is to take the time that meets the requirements in the past 30 days and convert it to a UNIX timestamp. Then the inner layer circulates the two timestamps for integral transmission.
As mentioned before, the dark magic array opened up by the outer cycle is full. But after observation, we can find that the whole loop is actually made up of two completely unrelated tasks: "pick date and prepare time stamp" and "send reward points".
How the complex cycle body responds to the new demand
What is the harm of such code? Let me tell you.
One day, the product came to say that some users stayed up in the middle of the night on weekends and were still browsing our website. We had to send them a notice to let them go to bed early in the future. So a new demand arises: "send a notification to users who have logged in between 3: 00 a.m. and 5: 00 a.m. on weekends in the past 30 days."
New problems follow. If you are as sharp as you, you can certainly see at a glance that the requirements of this new requirement in the user filtering section are very similar to the previous requirements. However, if you open the previous loop body again, you will find that the code cannot be reused at all, because inside the loop, different logic is completely coupled. ☹️
In the computer world, we often use the word "coupling" to describe the relationship between things. In the above example, "picking time" and "sending points" are in the same loop, establishing a very strong coupling relationship.
In order to better reuse the code, we need to decouple the "pick time" part of the function from the loop body. And our old friend, "generator function" is the best choice for this job.
Decouple the loop body using the generator function
To decouple the "pick time" part from within the loop, we need to define a new generator function gen_weekend_ts_ranges () that is specifically used to generate the desired UNIX timestamp:
Def gen_weekend_ts_ranges (days_ago, hour_start, hour_end): "generate a specific time range on Saturdays and Sundays in the past And return "" for days_delta in range (days_ago): dt = datetime.date.today ()-datetime.timedelta (days=days_delta) # 5: Saturday, 6: Sunday if dt.weekday () not in (5,6): continue time_start = datetime.datetime (dt.year, dt.month, dt.day, hour_start, 0) time_end = datetime.datetime (dt.year, dt.month, dt.day, hour_end, 0) # convert to unix timestamp with UNIX timestamp The subsequent ORM query requires ts_start = time.mktime (time_start.timetuple ()) ts_end = time.mktime (time_end.timetuple ()) yield ts_start, ts_end
With this generator function, the old requirement "send bonus points" and the new requirement "send notification" can be reused in the loop to complete the task:
Def award_active_users_in_last_30days_v2 (): "" send bonus points "for ts_start, ts_end in gen_weekend_ts_ranges (30, hour_start=20, hour_end=23): for record in LoginRecord.filter_by_range (ts_start, ts_end): send_awarding_points (record.user_id, 1000) def notify_nonsleep_users_in_last_30days ():"send Notification"for ts_start" Ts_end in gen_weekend_ts_range (30, hour_start=3, hour_end=6): for record in LoginRecord.filter_by_range (ts_start, ts_end): notify_user (record.user_id, 'You should sleep more')
We first briefly explained the definition of the "tunnel" loop code. Then the first suggestion is put forward: use the modifier function to improve the loop. Then I virtualized a business scenario that described the importance of dismantling the code in the loop according to duty.
A summary of some key points:
Using functions to modify the looped object itself can improve the code in the loop
There are many utility functions in itertools that can be used to improve loops.
Using generator functions, you can easily define your own modifier functions.
Inside the loop, it is a place where "code ballooning" can easily occur.
Please use generator functions to decouple code blocks with different responsibilities within the loop for better flexibility
The answers to the two questions about the Python writing cycle are shared here. I hope the above content can be of some help to you. If you still have a lot of doubts to be solved, you can follow the industry information channel to learn more about it.
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.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.