常见的 Python 编程错误

nyyb 8年前


这里总结了我多年来进行Python开发所犯的一些错误。虽然算不上一个『权威』列表,但这是我发现我的同事和朋友都常犯的错误类型。如果你觉得还有其他的错误需要补充,请在评论里告诉我!

错误 1# 在遍历的过程中修改列表

Python

>>> li=[1,2,3]    >>> for i in li:    ...    i.append(4)
>>>li=[1,2,3]     >>>foriinli:     ...    i.append(4)

这个有限循环变成了无限循环

错误 2# 错误理解了 Python 变量作用域

当一个变量在函数里被赋值时,Python 会假定它是在本函数内部定义的

Python

>>>i=[1,2,3]    >>>def print_i():    …     print i    [1,2,3]    >>>def modify_i():    …     i=i+[4,5]
>>>i=[1,2,3]     >>>defprint_i():     …    printi     [1,2,3]     >>>defmodify_i():     …    i=i+[4,5]

错误 3# 认为 True 和 False 是关键字

在 Python 2.x 版本中,True 和 False 不是关键字,所以

Python

>>>True = False    >>>if True == False:    …     print “end of the world”
>>>True=False     >>>ifTrue==False:     …    print“endoftheworld”

错误 4# Python 2.x 和 Python 3.x 之间的差别

在 Python 2.x 中

Python

>>>print “hello world”    hello world
>>>print“helloworld”     hello world

在 Python 3.x 中

Python

>>>print “hello world”    File “<stdin>”, line 1    print “hello”    ^    SyntaxError: invalid syntax    >>>print (“hello world”)    hello world
>>>print“helloworld”     File“<stdin>”,line1     print“hello”     ^     SyntaxError:invalidsyntax     >>>print(“helloworld”)     hello world

错误 5# 数据结构不是不可变对象

Python

>>>li1 = []    >>>li2=li1    >>>li2.append(1)    >>>print li1    [1]
>>>li1=[]     >>>li2=li1     >>>li2.append(1)     >>>printli1     [1]

这是因为我们只创建了一个对象,然后给它绑定了不同的名字。因此当你修改这个对象时,所有指向该对象的变量都会被改变。

错误 6# 在异常处理块中指定了错误的参数

Python

>>>try:  …     int(“z”)  >>>except IndexError, ValueError:  …     pass
>>>try:  …    int(“z”)  >>>exceptIndexError,ValueError:  …    pass

这段代码无法正常运行,因为 IndexError 是你要捕获的异常类型,ValueError 是指你要把捕获到的异常赋值给这个变量名

捕获多种异常的正确代码应该是这样:

Python

>>>try:  …     int(“z”)  >>>except (IndexError, ValueError):  …     pass
>>>try:  …    int(“z”)  >>>except(IndexError,ValueError):  …    pass

错误 7# is 和 == 操作并不一样

Python

>>> a=257    >>> b=257    >>> a is b    False    >>> a == b    True    >>> id(a)    23486712    >>> id(b)    23486736
>>>a=257     >>>b=257     >>>aisb     False     >>>a==b     True     >>>id(a)     23486712     >>>id(b)     23486736

is 操作检查两个对象是不是同一个对象,而 == 操作检查两个对象的值是否相等。

错误 8# import 语句只在第一次生效

你可以通过在交互提示符下 import 一个文件来执行它,但在每一次会话中,这个只会生效一次。之后的 import 只是简单的返回一个已经载入的模块。想要强制 Python 重新导入并返回一个文件的代码,可以执行 reload(module)函数。当你想这么做的时候,请确保使用 reload 函数来重新导入,而非再次 import。

错误 9# 整数除法

Python

>>> 5/2  2
>>>5/2  2

你可能想要的是:

Python

&gt;&gt;&gt; 5.0/2  2.5
>>>5.0/2  2.5

除法操作至少要有一个操作数是 float 类型。

错误 10# 没有正确理解类变量

Python

>>> class X(object):  …     a = 1  …  >>> class Y(X):  …     pass  …  >>> class Z(X):  …     pass  …  >>> print X.a, Y.a, Z.a  1 1 1
>>>classX(object):  …    a=1  …  >>>classY(X):  …    pass  …  >>>classZ(X):  …    pass  …  >>>printX.a,Y.a,Z.a  111

当 Y 的变量 a 改变时

Python

>>> Y.a = 5  >>> print X.a, Y.a, Z.a  1 5 1
>>>Y.a=5  >>>printX.a,Y.a,Z.a  151

这个结果和我们的预期一样,但是当我们改变 X 的变量 a 时

Python

>>> X.a = 3  >>> print X.a, Y.a, Z.a  3 5 3
>>>X.a=3  >>>printX.a,Y.a,Z.a  353

和字典一样,类变量是在内部处理的,并遵循一种 方法解析顺序(Method Resolution Order ,MRO)。在上述代码中,因为在类 Z 中没有找到该属性,它会去它的基类(在上例中只有 X,尽管 Python 支持多重继承)中搜索。换句话说,Z 不像 X,它没有自己的属性。因此对 Z.a 的引用实际上指向了 X.a。除非正确处理这个地方,否则很容易出问题。