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 are the deep bottomless pits in Python?

2025-02-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

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

Editor to share with you Python in the bottom of the pit, I believe that most people do not know much about it, so share this article for your reference, I hope you will learn a lot after reading this article, let's go to know it!

Python is a clear and concise language, and if you don't know the details, you will fall into those "pits" that don't know the bottom.

List creation and reference

Creation of nested lists

Use the * sign to create a nested list:

Li = [[]] * 3 print (li) # Out: [], [], []]

In this way, you can get a nested list containing three list, and let's add an element to the first list:

Li [0] .append (1) print (li) # Out: [[1], [1], [1]

As you can see from the output, we only add an element to the first element, and as a result, all three list add one element. This is because instead of creating three different list, [[]] * 3 creates three objects that point to the same list, so when we manipulate the first element, the contents of the other two elements also change. The effect is equivalent to the following code:

Li = [] element = [[]] li = element + element + element print (li) # Out: [[], []] element.append (1) print (li) # Out: [[1], [1], [1]]

We can print out the memory address of the element and find out:

Li = [[]] * 3 print ([id (inner_list) for inner_list in li]) # Out: [6830760, 6830760, 6830760]

At this point, we can understand why. So how do you solve it? You can do this:

Li = [[] for _ in range (3)]

So we created three different list objects

Print ([id (inner_list) for inner_list in li]) # Out: [6331048, 6331528, 6331488]

References to list elements

Do not use indexing methods to traverse list, for example:

For i in range (len (tab)): print (Ta [I])

A better way is:

For elem in tab: print (elem)

The for statement automatically generates an iterator. If you need to index locations and elements, use the enumerate function:

For I, elem in enumerate (tab): print (I, elem))

Note the use of the = symbol

If (var = = True): # if condition holds if (var! = True) when var is: True, 1, 1.0, 1L: # if condition holds if (var = = False) when var is not True and 1: # when var is False or 0 (or 0.0,0L) 0j) if condition holds if (var = = None): # var is None if condition holds if var: # when var is not empty (None or size 0) object string/list/dictionary/tuple, non-0 and other if conditions hold if not var: # when var empty (None or size 0) object string/list/dictionary/tuple If conditions such as non-0 hold if var is True: # only when var True if conditions hold 1 not even if var is False: # only when var False if conditions hold 0 and if var is None: # and var = = None agree

Catch exception due to early check

Less elegant code:

If os.path.isfile (file_path): file = open (file_path) else: # do something

Better practice:

Try: file = open (file_path) except OSError as e: # do something

It can be more concise in python2.6+:

With open (file_path) as file:

The reason for this use is that it is more general to write. For example, if file_path sends you a None, you will be blind, and you have to judge whether it is None or not. If you do not judge, you will have to catch exceptions. If you judge, the code will be written a lot.

Class variable initialization

Do not initialize class properties outside the init function of an object. There are two main problems.

If the class property changes, the initial value changes.

If you set the mutable object to the default value, you will get the same object that is shared across instances.

Error demonstration (unless you want static variables)

```class Car (object): color = "red" wheels = [Wheel (), Wheel ()] ```

The right thing to do:

````class Car (object): def _ _ init__ (self): self.color = "red" self.wheels = [Wheel (), Wheel ()] ```* * function default parameter * * ``def foo (li= []): li.append (1) print (li) foo ([2]) # Out: [2,1] foo ([3]) # Out: [3,1] ````

The code behaves as expected, but what if we don't pass parameters?

````foo () # Out: [1] As expected...foo () # Out: [1,1] Not as qualified.. ```

This is because the function parameter type is confirmed by definition rather than run time, so li points to the same list object in two function calls, and if you want to solve this problem, you can do this:

```def foo (li=None): if not li: li= [] li.append (1) print (li) foo () # Out: [1] foo () # Out: [1] ```

Although this solves the above problem, the output of some other objects, such as zero-length strings, is not what we want.

```x = [] foo (li=x) # Out: [1] foo (li= ") # Out: [1] foo (li=0) # Out: [1] ```

The most common method is to check whether the parameter is None.

```def foo (li=None): if li is None: li= [] li.append (1) print (li) foo () # Out: [1] ````* * modify during traversal * *

The for statement generates an iterator when traversing the object, and if you modify the object during traversal, it will produce unexpected results:

Alist = [0,1,2] for index, value in enumerate (alist): alist.pop (index) print (alist) # Out: [1]

The second element is not deleted because iterations traverse the index sequentially. The above loop is iterated twice, and the result is as follows:

# Iteration # 1 index = 0 alist = [0,1,2] alist.pop (0) # removes'0' # Iteration # 2 index = 1 alist = [1,2] alist.pop (1) # removes'2' # loop terminates, but alist is not empty: alist = [1]

If you avoid this problem, you can create another list

Alist = [for index, item in reversed (list (enumerate (alist)): # delete all even items if item% 2 = = 0: alist.pop (index) print (alist) # Out: [1,3,5,7]

Integer and string definition

Python pre-caches an interval of integers to reduce memory operations, but as such, it sometimes makes strange errors, such as:

>-8 is (- 7-1) False >-3 is (- 2-1) True

Another example.

>

Through constant testing, you will find that all integers in this range (- 3256) return True, and some even (- 8257). By default, [- 5256] is created and cached the first time the interpreter is started, which is why the above strange behavior occurs. This is a common but easily overlooked pit. The solution is to always use the equality (= =) operator instead of the identity (is) operator to compare values.

Python also retains references to commonly used strings and can produce similar confusing behavior when comparing the identity (that is, use) of is strings.

> > 'python' is' py' + 'thon'True

Python strings are cached, all python strings are references to this object, and identity comparison fails for unusual strings, even if the strings are equal.

> 'this is not a common string' is' this is not' +'a common string'False > 'this is not a common string' = =' this is not' +'a common string'True

So, just like the integer rule, always use the equal (= =) operator instead of the identity (is) operator to compare string values.

List derivation and variable leakage in loops

Here's an example:

I = 0a = [i for i in range (3)] print (I) # Outputs 2

The list derivation in python2 changed the value of the I variable, and python3 fixed this problem:

I = 0 a = [i for i in range (3)] print (I) # Outputs 0

Similarly, for loops have no private scope for their iteration variables

I = 0 for i in range (3): pass print (I) # Outputs 2

This behavior occurs in Python 2 and Python 3.

To avoid the problem of leaking variables, use new variables in list derivation and for loops.

Or operator

For example

If a = = 3 or b = = 3 or c = = 3:

This is simple, but look at another one:

If an or b or c = = 3: # Wrong

This is because or has a lower priority than = =, so the expression will be evaluated as if (a) or (b) or (c = = 3):. The correct way is to check all conditions explicitly:

If a = = 3 or b = = 3 or c = = 3: # Right Way

Alternatively, you can use the built-in function any () instead of the linked or operator:

If any ([a = = 3, b = = 3, c = = 3]): # Right

Or, to make it more efficient:

If any (x = = 3 for x in (a, b, c)): # Right

Write it in a shorter way:

If 3 in (a, b, c): # Right is all the contents of this article entitled "what are the bottomless pits in Python?" Thank you for reading! I believe we all have a certain understanding, hope to share the content to help you, if you want to learn more knowledge, welcome to follow the industry information channel!

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