10 common mistakes in Python programmer development _python

Source: Internet
Author: User

Python is a simple and easy to learn programming language, concise and clear syntax, and has a rich and powerful class library. Unlike most other programming languages, which use braces differently, it uses indenting to define statement blocks.

In normal work, Python developers are easy to make a few small mistakes, these errors are easy to avoid, this article summed up the Python developers the most common mistakes 10, together to see if you have been shot.

1. Abusing the expression as the default value of the function parameter

Python allows developers to specify a default value for function parameters, although this is a feature of the language, but when the parameters are variable, it can easily lead to confusion, for example, the following function definition:

Copy Code code as follows:

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

In the above code, once the Foo () function is called repeatedly (without specifying a bar parameter), it will always return ' bar ' because no arguments are specified, and foo () will give [] each time it is invoked. Here's a look at the results of this:
Copy Code code as follows:

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

Solution:

Copy Code code as follows:

>>> 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. Using class variables incorrectly

Let's look at the following example:

Copy Code code as follows:

>>> class A (object):
.. x = 1
...
>>> class B (A):
. Pass
...
>>> class C (A):
. Pass
...
>>> print a.x, b.x, c.x
1 1 1

It makes sense:

Copy Code code as follows:

>>> b.x = 2
>>> print a.x, b.x, c.x
1 2 1

Let's go over it again:
Copy Code code as follows:

>>> a.x = 3
>>> print a.x, b.x, c.x
3 2 3

Only to change the a.x, why c.x also follow the change.

In Python, class variables are processed internally as dictionaries and follow the method parsing order (MRO). In the above code, because property X is not found in Class C, it looks for its base class (only a in the example above, although Python supports multiple inheritance). In other words, C has no x attribute and is independent of a, so referencing c.x is actually a reference to a.x.

3. Specify incorrect parameters for the exception

Suppose the code has the following code:

Copy Code code as follows:

>>> 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 here is that the except statement does not need this way to specify the list of exceptions. However, in Python 2.x, the except exception,e is usually used to bind the second parameter in the exception so that it can be examined further. Therefore, in the above code, the Indexerror exception is not captured by the except statement, and the exception is finally bound to a parameter named Indexerror.

The correct way to catch multiple exceptions in an exception statement is to specify the first argument as a tuple that contains all the caught exceptions. At the same time, using the AS keyword to ensure maximum portability, both Python 2 and Python 3 support this syntax.

Copy Code code as follows:

>>> Try:
... l = ["A", "B"]
... int (l[2])
... except (ValueError, Indexerror) as E:
. Pass
...
>>>

4. Misunderstanding the Python rule scope

Python's scope parsing is based on LEGB rules, which are local, enclosing, Global, and built-in. In fact, this parsing method has some mystery, look at the following example:

Copy Code code as follows:

>>> 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 Foo
unboundlocalerror:local variable ' x ' referenced before assignment

Many people will be surprised when they add a parameter statement to the function body of the work and report unboundlocalerror errors in the code of the previous work (click here to see more detailed descriptions).

It is easy for developers to make this mistake when using a list, and look at the following example:

Copy Code code as follows:

>>> 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 Foo
unboundlocalerror:local variable ' LST ' referenced before assignment

Why Foo2 fail and foo1 run normally?

The answer is the same as the previous example, but there are some subtleties. Foo1 is not assigned to LST, and Foo2 is assigned a value. 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 a value that is assigned to LST based on the LST itself, which is not actually determined.

5. Modify the Traversal list

The following piece of code is obviously wrong:

Copy Code code as follows:

>>> 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 a list while traversing. A little bit of experience doesn't make a man.

Modify the code above to execute correctly:

Copy Code code as follows:

>>> 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 in a closed package

Look at the following example:

Copy Code code as follows:

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

The results you expect are:
Copy Code code as follows:

0
2
4
6
8

As a matter of fact:
Copy Code code as follows:

8
8
8
8
8

is not very surprised! This occurs primarily because of the late-bound behavior of Python, which is used in closures while internal functions call it.

Solution:

Copy Code code as follows:

>>> def create_multipliers ():
... return [lambda x, i=i:i * x to I in range (5)]
...
>>> for multiplier in Create_multipliers ():
... print multiplier (2)
...
0
2
4
6
8

7. Create a circular module dependency

Suppose there are two files, a.py and b.py, and then each of them is imported, as follows:

In the a.py:

Copy Code code as follows:

Import b

def f ():
Return b.x

Print F ()


In the b.py:
Copy Code code as follows:

Import a

x = 1

def g ():
Print A.F ()


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

Copy Code code as follows:
>>> Import a
1

Can work well, perhaps you will be surprised. After all, we did have a circular import here, shouldn't there be a problem?

The mere existence of a circular import is not a problem for Python itself, and if a module is imported, Python will not attempt to re-import it. Based on this, each module may encounter problems at run time when it attempts to access a function or variable.

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

Copy Code code as follows:

>>> Import B
Traceback (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 F
Return b.x
Attributeerror: ' Module ' object has no attribute ' x '

Error, the problem here is that you also try to import a.py during the import of b.py, which calls F () and attempts to access b.x. But b.x is not defined.

You can fix this by simply modifying the G () function that b.py imports into a.py:

Copy Code code as follows:

x = 1
def g ():
Import a # This'll be evaluated only when G () called
Print A.F ()

Whenever you import, everything works:

Copy Code code as follows:

>>> Import B
>>> B.G ()
1 # printed a A since module ' a ' calls ' Print f () ' at the end
1 # Printed A second time, this one's our call to ' G '

8. Conflict with Python standard library module name

Python has a very rich module library and supports "out-of-the-box". Therefore, if you do not deliberately avoid it, it is easy to have a naming conflict event. For example, there may be a email.py module in your code that, because of its name, is likely to conflict with the standard library module that Python brings with it.

9. The difference between python2.x and python3.x is not dealt with as stipulated

Take a look at foo.py:

Copy Code code as follows:

Import Sys

def 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 ()

It works well in Python 2:

Copy Code code as follows:

$ python foo.py 1
Key error
1
$ Python foo.py 2
Value error
2

But in Python 3:
Copy Code code as follows:

$ python3 foo.py 1
Key error
Traceback (most recent call last):
File "foo.py", line, in <module>
Bad ()
File "foo.py", Line and bad
Print (e)
Unboundlocalerror:local variable ' e ' referenced before assignment

Solution:

Copy Code code as follows:

Import Sys

def 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 ()

To run the results in py3k:

Copy Code code as follows:
$ python3 foo.py 1
Key error
1
$ Python3 foo.py 2
Value error
2

There are a lot of caveats and discussions in the Python recruitment guide about Python 2 and Python 3 that need attention when porting code, and you can go and see.

10. Misuse of __DEL__ methods

For example, here is a file called mod.py:

Copy Code code as follows:

Import Foo
Class Bar (object):
...
def __del__ (self):
Foo.cleanup (Self.myhandle)

Below, you do the following in the another_mod.py file:
Copy Code code as follows:

Import MoD
Mybar = mod. Bar ()

You will get a Attributeerror exception.

As for why the exception appears, click here to see the details. When the interpreter shuts down, the module's global variables are all set to none. So, in the example above, when __del__ is called, Foo is all set to none.

A good solution is to use Atexit.register () instead. Incidentally, when the program completes, the handler that you registered will stop working before the interpreter shuts down.

To fix the code for the above problem:

Copy Code code as follows:

Import Foo
Import atexit

def cleanup (handle):
Foo.cleanup (handle)


Class Bar (object):
def __init__ (self):
...
Atexit.register (cleanup, self.myhandle)

With the normal termination of the program, this implementation provides a neat and reliable way to invoke any functionality that needs to be cleaned up.

Summarize

Python is a powerful and flexible programming language with many mechanisms and patterns to improve productivity dramatically. As with any language or software tool, there is a restrictive understanding or appreciation of one's ability, some of which are more harmful than good, and sometimes bring some pitfalls. Understanding the nuances of a language and the common pitfalls can help you walk farther along the path of the developer.

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.