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

What is the common anti-pattern of Python?

2025-01-31 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)05/31 Report--

This article mainly introduces "what is the common anti-pattern of Python". In the daily operation, I believe that many people have doubts about what the common anti-pattern of Python is. The editor consulted all kinds of materials and sorted out simple and easy-to-use methods of operation. I hope it will be helpful to answer the doubt of "what is the common anti-pattern of Python?" Next, please follow the editor to study!

1. Use map () and filter () on Iterable objects

Built-in map and filter can help us transform iterable objects in Python through functional programming.

Both methods take a function and an iterable as arguments and return the corresponding object.

You can convert the object to a list by passing it as an argument to the built-in list constructor in Python.

We often use the lambda function as a parameter to the map and filter functions:

My_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # multiply each element by 2 print (map (lambda x: X * 2, my_list)) # [2, 4, 6, 8, 10, 12, 14, 16, 18, 20] # filter out even print (list (lambda x: X% 2 = 0, my_list)) # [2, 4, 6, 8, 10]

The above code looks rather cumbersome and unclear. Using list understanding, you can achieve the same result:

My_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # same print as map ([x * 2 for x in my_list]) # [2, 4, 6, 8, 10, 12, 14, 16, 18, 20] # same print as filter ([x for x in my_list if x% 2 = 0]) # [2, 4, 6, 8, 10]

Without the lambda function, list comprehension becomes more readable and concise.

two。 Use list to understand when the input is large

List understanding helps us to write clear and concise code.

However, list understanding always creates a list for each value in iterable. When the input is very large, it will lead to the problem of excessive memory footprint: our machines may crash.

Generator expressions combine the advantages of list understanding and generator, and provide a more effective way to deal with large input sequences.

To create a generator expression, simply replace the [] square brackets in the list with () square brackets.

Instead of creating an entirely new list, the generator expression creates an iterator.

This slows down creation and optimizes memory allocation. We can use the next function or iterate through each subsequent element of the generator expression.

My_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] my_gen_expr = (x * 2 for x in my_list) print (next (my_gen_expr)) print (next (my_gen_expr)) # > # 2 # 4 for x in my_gen_expr: print (x) # > > # 6 # 8 # 10 # 12 # 16 # 18 # 20

Note: generator expressions are stateful, so be careful when reusing them. If you want to use an iterator multiple times, you may need to recreate the iterator.

3. Cases where range () is not used

The range function is useful for iterating over integers.

For i in range (10): print (I)

When iterating over list-like data structures, we can rely entirely on the for loop syntax to access each project. The code is as follows:

My_list = [2,4,6,8,10] for item in my_list: print (item) # Output: # 2 # 4 # 6 # 8 # 10

However, when we want to access indexes and elements, we can use the range method under the list length, as follows:

My_list = [2,4,6,8,10] for i in range (len (my_list)): print ("index:", I, "value:", my_ list [I]) # Output: # index: 0 value: 2 # index: 1 value: 4 # index: 2 # index: 3 value: 8 # index: 4 value: 10

The code looks unreadable because we have to call len on the list and then wrap the output with the range method. In order to make the code more python-style, we must improve the readability of the code.

A better approach is to call the enumerate function on the list object. This creates a generator that generates indexes and values for list items.

My_list = [2,4,6,8,10] for I, v in enumerate (my_list): print ("index:", I, "value:", v) # Output: # index: 0 value: 2 # index: 1 value: 4 # index: 2 value: 6 # index: 3 value: 8 # index: 4 value: 10

Does the code look cleaner?

4. The problem of missing keys in dictionaries

Dictionary is a very popular data structure with the ability to quickly access, assign, insert and delete.

However, novice developers often encounter problems when accessing keys that do not exist in the dictionary.

Crypto_price = {"Bitcoin": 64000, "Ethereum": 2300, "Dogecoin": 0.12} crypto_price ["XRP"]

One of the ways to deal with this kind of problem is to check whether a key exists in the dictionary, as follows:

Key = "XRP" if key not in crypto_price: crypto_ print [key] = 1.2 print (crypto_ print [key])

Another method is to use the try/except block, as follows:

Key = "XRP" try: xrp = crypto_ price [key] except raise KeyError: xrp = 1.2 crypto_ price [key] = xrp

The above code does achieve our goal, but we can further improve it by using the dictionary method get.

Get the value of the corresponding key by using the get method instead of using square brackets [] to access the dictionary key.

In addition, if the key does not exist, the get method returns None instead of throwing a KeyError. If a key is missing instead of keyless, you can also pass parameters to the get method to get the default value.

Key = "XRP" if crypto_price.get ("XRP") is None: crypto_price ["XRP"] = 1.2ada = crypto_price.get ("ADA", 0) # Prints 0 print (ada) 5. Design of inert keywords and position parameters

The Python function can accept both position and keyword parameters.

The position parameter is a name that is not followed by an equal sign (=) and a default value.

The keyword argument is followed by an equal sign and an expression that gives its default value.

Thanks to this design, the creation and reuse of python functions are very flexible.

However, when defining functions, incorrect design choices can lead to errors in your code that are difficult to fix.

Let's take the function of calculating compound interest as an example:

# compound interest calculator annual / monthly compound interest def calculate_compound_interest (principal, rate, time_in_years, compounded_monthly To_string): t = 1 if compounded_monthly: t = 12 amt = principal * (1 + rate/ (t * 100)) * * (time_in_years * t) if to_string: return f "${amt-principal:.2f}" return amt-principal calculate_compound_interest (100,5,2, False, False) # 10.25

One problem with calling a function is that the two Boolean parameters (compounded_monthly and the ending to_string) can easily be confused with each other. This leads to untraceable problems.

We can improve readability by changing the function definition as follows:

# compound interest calculator compound interest def calculate_compound_interest (principal, rate, time_in_years, compounded_monthly=False, to_string=False):

By specifying two Boolean parameters as keyword parameters, the function caller can explicitly specify the Boolean values to be set, which override the default values.

Calculate_compound_interest (100,5,2, compounded_monthly=True) # 10.49413355583269 calculate_compound_interest (100,5,2, to_string=True) #'$10.25'

However, this can still be problematic, mainly because keyword parameters are optional because no caller forces them to be used as keyword parameters.

Therefore, we can still call the function using the old method:

Calculate_compound_interest (100,5,2, False, False)

The solution to this problem is to force Boolean parameters to be keywords only when defining functions:

# compound interest calculator compound interest def calculate_compound_interest (principal, rate, time_in_years, *, # Changed compounded_monthly=False, to_string=False):

We see that the * symbol indicates the end of the positional parameter and the beginning of only the keyword parameter.

If it is called like this:

Calculate_compound_interest (100,5,2, False, False)

The following error occurs:

-TypeError Traceback (most recent call last) in-> 1 print (calculate_compound_interest (1000, 5, 2, False) False)) TypeError: calculate_compound_interest () takes 3 positional arguments but 5 were given

However, the keyword parameters and their default behavior will remain the same, as follows:

Alculate_compound_interest (100,5,2, compounded_monthly=True) # 10.49413355583269 calculate_compound_interest (100,5,2, to_string=True) #'$10.25'

However, there is still a problem.

Suppose the caller decides to mix location and keywords for the first three required parameters (principal, rate, time in years).

If the function parameter names of these three parameters change, we will see the Python interpreter. It would say:

# compound interest calculator def calculate_compound_interest (p, r, t_in_y, *, # Changed compounded_monthly=False, to_string=False): calculate_compound_interest (principal=1000, rate=5, time_in_years=2) calculate_compound_interest (1000, 5, time_in_years=2)

The following error occurs:

-TypeError Traceback (most recent call last) in-> 1 calculate_compound_interest (principal=1000, rate=5) Time_in_years=2) TypeError: calculate_compound_interest () got an unexpected keyword argument 'principal'-TypeError Traceback (most recent) Call last) in-> 1 calculate_compound_interest (1000 5, time_in_years=2) TypeError: calculate_compound_interest () got an unexpected keyword argument 'time_in_years'

Because we did not consider the caller's explicit use of positional parameters, the code was interrupted.

A solution has been introduced in python3.8 where we can redefine the function with the / parameter, which indicates the end position of only the position parameter. The code is as follows:

# compound interest calculator compound interest def calculate_compound_interest (p, r, t_in_y, /, *, # change compounded_monthly=False, to_string=False):

Now calling the function in this way produces the correct result:

Calculate_compound_interest (100,5,2, compounded_monthly=True) # 10.49413355583269 calculate_compound_interest (100,5,2, to_string=True) #'$10.25'

However, if we call:

Calculate_compound_interest (pendant 1000, rDNA 5, t_in_y=2)

The corresponding error is also displayed:

-TypeError Traceback (most recent call last) in-> 1 calculate_compound_interest T_in_y=2) 2 TypeError: calculate_compound_interest () got some positional-only arguments passed as keyword arguments:'p, r, tactile. The study on "what is the common anti-pattern of Python" is over, hoping to solve everyone's doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!

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

Internet Technology

Wechat

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

12
Report