My personal definition of a trap is this: code looks like it works, but not in the way you “take it for granted”. If a piece of code goes straight wrong and throws an exception, I don’t think it’s a trap. For example, Python programmers should encounter UnboundLocalError as an example:

There are more advanced versions of “UnboundLocalError” :

This Error may be confusing to many people who are new to Python. But I don’t think this is a trap, because the code is bound to report errors, rather than silently running in the wrong way. Not afraid of real people, but afraid of hypocrites. I think flaws are hypocrites.

So what are the real traps in Python


First: use a mutable object as the default argument

This estimate is by far the best known. Python, like many other languages, provides default arguments. Default arguments are a really good thing, allowing function callers to ignore details (such as GUI programming, Tkinter, QT), and are useful for lambda expressions. But if you use mutable objects as default arguments, things are not so pleasant

Surprise or not? ! The reason is that everything in Python is an object, including functions, and the default argument is just an attribute of a function. The default parameters are already evaluated when the function is defined.

Default parameter values are evaluated when the function definition is executed.

A more appropriate example on StackOverflow is that default parameters are evaluated when defined, not when called.

Python Docoment provides a standard workaround:

A way around this is to use None as the default, and explicitly test for it in the body of the function

Second: x += y vs x = x + y

In general, the two are equivalent, or at least appear equivalent (which is also the definition of the trap — both look OK, but not necessarily correct).

Uh, hit in the face by the speed of light?

The former x points to a new object, the latter x is modified in the original object, of course, which effect is correct depends on the application scenario. At the very least, they are not always the same

Third, the magic parenthesis — ()

Parentheses are widely used in various programming languages. In Python, parentheses are also used to represent tuples, which are immutable sequences.

But what if there’s only one element

Amazing or not, to represent a tuple with only one element, the correct position is:

Fourth: Generate a list whose elements are lists

This is kind of like a two-dimensional array, but it’s also possible to generate a list of elements that are dictionaries, or more generally, a sequence of elements that are mutable objects

It’s very simple:

It looks good, simple and clear, but

I’m guessing that’s not what you’re expecting, because list is a mutable object in Python, and this is all pointing to the same mutable object, the correct posture

Another real-world coding problem, dict.fromkeys, works the same way: you create dict values that all point to the same object.

fromkeys(seq[, value])
Copy the code

Create a new dictionary with keys from seq and values set to value.

Fifth, modify the list as you access it

Lists are used extensively in Python, and of course elements are often added or removed when accessing lists. For example, the following function attempts to remove elements in a list that are multiples of 3:

Test it out,

There’s nothing wrong with that, but it’s just luck, right

In the example above, the 6 element is not deleted. If you print idx in modify_lst, the item will notice that the LST is getting shorter, but the IDX is increasing, so in the case of the error above, when 3 is deleted, 6 becomes the second element of the LST (starting from 0). In C++, the same problem occurs when iterators are used to delete elements while iterating through containers.

If the logic is simple, it is a good idea to use list Comprehension

Sixth, closures and lambda

This is an old story, and it happens in other languages as well. Let’s start with an example:

The return value of create_multipliers is a list, and each element of the list is a function that multiplies the input parameter x by a multiple of I. The expected result was 0,2,4,6,8. But it turned out to be 5 eights.

Since lambda is often used when this trap occurs, it may be assumed that lambda is to blame, but Lambda says it does not want to take the blame. The nature of the problem lies in the python property search rules, LEGB (local, enclousing, global, bulitin), in the above example, I is in enclousing, while python closures are late binding, This means that the values of the variables used in the closure are queried when the inner function is called.

The solution is simple: change the closure scope to a local scope.

Seventh, define del

Most of the computer students may be the first to learn C, C++, construction, destructor should be very familiar with the concept. So when you switch to Python, you naturally want to know if there’s a function. For example, RAII, well known in C++, manages the declaration cycle of resources (such as memory, file descriptors) through construction and destruction. So what do you do in Python to achieve the same effect, which is to find a function that must be called when an object is destroyed, and so you found the init, del function, and maybe just wrote two examples and found that it does work. But you might actually fall into a trap, which is described in Python DocumNet:

Circular references which are garbage are detected when the option cycle detector is enabled (it’s on by default), but can only be cleaned up if there are no Python-level del() methods involved.

Simply put, if an object in a circular reference has a DEL defined, then the Python GC cannot reclaim and, therefore, there is a risk of a memory leak

8. Different poses import the same Module

The example tweaks up on the StackOverflow example and assumes that there is now a package called mypackage that contains three Python files: mymodule.py, main.py, and init.py. Mymodule.py looks like this:

The code for main.py looks like this:

Run Python main.py and the result is as follows:

updated list [1] 4406700752
module in get 4406700920
lets check []
Copy the code

As you can see from the results, the myModule imported from add and get is not the same module with a different ID. Of course, in python2.7.10, line 13 of main.py is required to have this effect. Who would write line 13 like this, you might ask? In fact, many projects add a bunch of paths to sys.path for import purposes. It is necessary to agree on an import approach in a project

Ninth, Python upgrade

Python3. x is not backward compatible, so be careful when upgrading from 2.x to 3.x. Here are two things:

In python2.7, the return value of range is a list; In Python3. x, a range object is returned.

Map (), filter(), dict.items() return lists in Python2.7, and iterators in 3.x. Of course, iterators are mostly better choices and are more pythonic, but they have the disadvantage of only iterating once. I also mentioned a bug caused by this in my Instagram post.

Tenth: ++ I – I

This trap mainly pits students from C and C++ backgrounds. In simple terms, ++ I is a plus sign for I twice, -i is a minus sign for I twice, and I stays the same.

11: setattr getattr getAttribute

There are a number of magic methods (similar to XX) in Python, many of which are related to attribute access, such as GET, set, delete_, getattr, setattr, delattr, and getAttribute. The first three descriptors are related to descriptor. For details, see Detailed Description of Python Descriptor. Getattr is surprisingly different from setattr, as described in the Python Attribute Look Up article. Getattr is called only when the default lookup mechanism fails to find an attribute. Setattr should be called setAttribute__.

Minus one, Gil

End with GIL, because GIL is an accepted flaw in Python!

Those of you coming from other languages might have seen Python using the threading module, taken it in, used it, found out it wasn’t working, and then said, what the hell

Conclusion:

There is no doubt that Python is a very easy and powerful language to learn. Python is very flexible and customizable. At the same time, there are some pitfalls, and understanding these pitfalls can help you better grasp and use the language. This article lists some of the flaws in Python, but it is an incomplete list that you are welcome to add.