The 10 most common mistakes made by Python developers are:

Source: Internet
Author: User

The 10 most common mistakes made by Python developers are:

Python is a simple and easy-to-learn programming language with simple and clear syntax and rich and powerful class libraries. Unlike most programming languages that use braces, indentation is used to define statement blocks.

In normal work, Python developers can easily make small mistakes, which are easily avoided. This article summarizes the 10 most common mistakes made by Python developers. Let's take a look at them, I wonder if you have been shot.

 

  1. Misuse expression as the default value of function parameters

Python allows developers to specify a default value for function parameters. Although this is a feature of the language, variable parameters can easily lead to confusion. For example, the following function definition:

>>> def foo(bar=[]):        # bar is optional and defaults to [] if not specified...    bar.append("baz")    # but this line could be problematic, as we'll see......    return bar

In the above Code, once the foo () function is repeatedly called (no bar parameter is specified), 'bar' is always returned. Because no parameter is specified, foo () [] is assigned each time it is called. The result is as follows:

>>> foo()["baz"]>>> foo()["baz", "baz"]>>> foo()["baz", "baz", "baz"]

Solution:

>>> def foo(bar=None):...    if bar is None:# or if not bar:...        bar = []...    bar.append("baz")...    return bar...>>> foo()["baz"]>>> foo()["baz"]>>> foo()["baz"]

  2. incorrect use of class variables

Let's take a look at the following example:

>>> class A(object):...     x = 1...>>> class B(A):...     pass...>>> class C(A):...     pass...>>> print A.x, B.x, C.x1 1 1

This makes sense:

>>> B.x = 2>>> print A.x, B.x, C.x1 2 1

Again:

>>> A.x = 3>>> print A.x, B.x, C.x3 2 3

Just changed A. x, why C. x also changed.

In Python, class variables are internally processed as dictionaries and follow the method parsing sequence (MRO ). In the above Code, because attribute x is not found in Class C, it will find its base class (in the above example, only A, although Python supports multi-inheritance ). In other words, C itself does not have the x attribute and is independent of A. Therefore, referencing C. x actually references A. x.

  3. Specify incorrect parameters for exceptions

Assume that the Code contains the following code:

>>> try:...     l = ["a", "b"]...     int(l[2])... except ValueError, IndexError:  # To catch both exceptions, right?...     pass...Traceback (most recent call last):  File "<stdin>", line 3, in <module>IndexError: list index out of range

The problem is that the T statement does not need to specify the exception list in this way. However, in Python 2.x, parse t Exception and eare usually used to bind the second parameter in the Exception for further checks. Therefore, in the above Code, the IndexError exception is not captured by the except T statement, and the exception is finally bound to a parameter named IndexError.

The correct way to capture multiple exceptions in an exception statement is to specify the first parameter as a tuple, which contains all caught exceptions. At the same time, the as keyword is used to ensure maximum portability. Both Python 2 and Python 3 support this syntax.

>>> try:...     l = ["a", "b"]...     int(l[2])... except (ValueError, IndexError) as e:  ...     pass...>>>

  4. misunderstanding of the Python rule Scope

The scope resolution of Python is based on LEGB rules, including Local, Enclosing, Global, and Built-in. In fact, this resolution method also has some mystery. Let's look at the example below:

>>> x = 10>>> def foo():...     x += 1...     print x...>>> foo()Traceback (most recent call last):  File "<stdin>", line 1, in <module>  File "<stdin>", line 2, in fooUnboundLocalError: local variable 'x' referenced before assignment

Many people will be surprised. When they add a parameter statement to the function body at work, the UnboundLocalError will be reported in the code of the previous work (Click here for a more detailed description ).

When using the list, developers can easily make this mistake. Let's take a look at the following example:

>>> lst = [1, 2, 3]>>> def foo1():...     lst.append(5)   # This works ok......>>> foo1()>>> lst[1, 2, 3, 5]>>> lst = [1, 2, 3]>>> def foo2():...     lst += [5]      # ... but this bombs!...>>> foo2()Traceback (most recent call last):  File "<stdin>", line 1, in <module>  File "<stdin>", line 2, in fooUnboundLocalError: local variable 'lst' referenced before assignment

Why does foo1 run normally when foo2 fails?

The answer is the same as the previous example, but there are some nuances. Foo1 is not assigned to lst, while foo2 is assigned. Lst + = [5] is actually lst = lst + [5], trying to assign a value to lst (therefore, suppose Python is in a local scope ). However, we are looking for the value specified to the lst Based on the lst itself, but it is not yet determined.

  5. Modify the traversal list

The following code is obviously incorrect:

>>> odd = lambda x : bool(x % 2)>>> numbers = [n for n in range(10)]>>> for i in range(len(numbers)):...     if odd(numbers[i]):...         del numbers[i]  # BAD: Deleting item from a list while iterating over it...Traceback (most recent call last):    File "<stdin>", line 2, in <module>IndexError: list index out of range

It is a low-level error to delete the list during traversal. People with a little experience will not commit crimes.

Modify the preceding code and execute it correctly:

>>> odd = lambda x : bool(x % 2)>>> numbers = [n for n in range(10)]>>> numbers[:] = [n for n in numbers if not odd(n)]  # ahh, the beauty of it all>>> numbers[0, 2, 4, 6, 8]

  6. How to bind a variable to a closure

Let's look at the example below:

>>> def create_multipliers():...     return [lambda x : i * x for i in range(5)]>>> for multiplier in create_multipliers():...     print multiplier(2)...

The expected result is:

<code>02468</code>

Actually:

<code>88888</code>

Not surprising! This is mainly because of the later binding behavior of Python. When this variable is used in the closure, internal functions call it again.

Solution:

>>> def create_multipliers():...     return [lambda x, i=i : i * x for i in range(5)]...>>> for multiplier in create_multipliers():...     print multiplier(2)...02468

  7. Create cycle module dependency

Assume that there are two files, a. py and B. py, and then import them respectively, as follows:

In a. py:

import bdef f():    return b.xprint f()

In B. py:

import ax = 1def g():    print a.f()

First, let's try to import a. py:

<code>>>> import a1</code>

You may be surprised to work well. After all, we have made a circular import here. Shouldn't it be a problem?

Only one loop import is not a Python issue. If a module is imported, Python will not try to re-import it. According to this, each module may encounter some problems during runtime when attempting to access functions or variables.

What happens when we try to import B. py (a. py was not previously imported ):

>>> import bTraceback (most recent call last):    File "<stdin>", line 1, in <module>    File "b.py", line 1, in <module>    import a    File "a.py", line 6, in <module>print f()    File "a.py", line 4, in freturn b.xAttributeError: 'module' object has no attribute 'x'

An error occurs. The problem here is that you need to try to import a. py during the process of importing B. py. In this way, you need to call f () and try to access B. x. However, B. x is not defined.

You can solve this problem by modifying the g () function that B. py imports to a. py:

x = 1def g():    import a# This will be evaluated only when g() is called    print a.f()

Everything can run normally at any time:

>>> import b>>> b.g()1# Printed a first time since module 'a' calls 'print f()' at the end1# Printed a second time, this one is our call to 'g'

  8. Conflict with the Python standard library module name

Python has a rich array of module libraries and supports "out-of-the-box ". Therefore, if you do not avoid it, it is easy to have a name conflict event. For example, there may be an email. py module in your code. Because the name is the same, it is likely to conflict with the standard library module that comes with Python.

  9. The difference between Python2.x and Python3.x was not handled as required

Let's take a look at foo. py:

import sysdef bar(i):    if i == 1:        raise KeyError(1)    if i == 2:        raise ValueError(2)def bad():    e = None    try:        bar(int(sys.argv[1]))    except KeyError as e:        print('key error')    except ValueError as e:        print('value error')    print(e)bad()

Python 2 can run well:

$ python foo.py 1key error1$ python foo.py 2value error2

But in Python 3:

$ python3 foo.py 1key errorTraceback (most recent call last):  File "foo.py", line 19, in <module>    bad()  File "foo.py", line 17, in bad    print(e)UnboundLocalError: local variable 'e' referenced before assignment

Solution:

import sysdef bar(i):    if i == 1:        raise KeyError(1)    if i == 2:        raise ValueError(2)def good():    exception = None    try:        bar(int(sys.argv[1]))    except KeyError as e:        exception = e        print('key error')    except ValueError as e:        exception = e        print('value error')    print(exception)good()

Running results in Py3k:

<code>$ python3 foo.py 1key error1$ python3 foo.py 2value error2</code>

The Python recruitment Guide contains many precautions and discussions about Python 2 and Python 3 during code porting.

  10. abuse the _ del _ Method

For example, there is a file named mod. py:

import fooclass Bar(object):       ...    def __del__(self):        foo.cleanup(self.myhandle)

In the another_mod.py file, perform the following operations:

import modmybar = mod.Bar()

You will get an AttributeError error.

Click here to view details about the exception. When the interpreter is disabled, all global variables of this module are set to None. Therefore, in the above example, when _ del _ is called, all foo has been set to None.

A good solution is to use atexit. register () instead. By the way, after the program is executed, the registered handler stops working before the interpreter is closed.

Code for fixing the above problem:

import fooimport atexitdef cleanup(handle):    foo.cleanup(handle)class Bar(object):    def __init__(self):        ...        atexit.register(cleanup, self.myhandle)

Under the premise of the normal termination of the program, this implementation provides a clean and reliable way to call any function to be cleared.

  Summary

Python is a powerful and flexible programming language with many mechanisms and modes to greatly improve work efficiency. Just like any language or software tool, people will have a restrictive understanding or appreciation of their abilities. Some of them have advantages over others, and sometimes they will bring some traps. Understanding the nuances of a language, understanding some common traps, helps you go further on the developer's path.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.