在学习过程中,偶然发现一个博客,写的关于python中常见的10个错误,觉得比较不错,整理一下。
原文见:
http://bookshadow.com/weblog/2014/05/14/top-10-mistakes-that-python-programmers-make/
具体如下:
1:函数参数默认值表达式的误用
def fun(friut=[]):
friut.append("apple")
print friut
fun() #['apple']
fun() #['apple', 'apple']
fun() #['apple', 'apple', 'apple']
目的是调用fun(),想得到“apple”,但是当多次调用,发现产生的结果和期望中不一样。
原因是:函数的缺省值只在函数定义时进行一次初始化。fun()函数在第一次定义时初始化为缺省值,后续调用时,
会继续沿用最开始初始化得到的那个列表。
解决如下:
def fun(friut=None):
if friut is None:
friut = []
friut.append("apple")
print friut
fun() #['apple']
fun() #['apple']
fun() #['apple']
2:类变量的误用
当子类没有独立于父类的属性时,对父类的属性进行的更改等相关操作。子类调用该属性时,也会发生变化,
其实子类调用该属性仅仅是对父类的引用。
class A(object):
a = 1
class B(A):
pass
class C(A):
pass
print A.a, B.a, C.a #1 1 1
B.a = 2
print A.a, B.a, C.a #1 2 1
A.a = 5
print A.a, B.a, C.a #5 2 5
3:异常块参数指定错误
使用try,except时。捕捉多个异常错误时。应使用as关键词。
try:
l = ["a", "b"]
int(l[2])
except (ValueError, IndexError) as e:
print 123
4:python作用域规则的误解
python的作用域规则基于LEGB规则(local局部,enclosing封闭,global全局,build-in内置)
比如:变量定义在函数外,在函数内对变量进行操作。当其他模块调用该函数数,就会出现UnboundLocalError错误
num1 = 1
def fun():
num1 += 1
print num1
fun() #UnboundLocalError: local variable 'num1' referenced before assignment
5:遍历列表时修改列表的值
在遍历时,不要从列表和数组中进行删除操作。在python中,可以使用列表解析来规避此问题。
num1 = lambda x: bool(x % 2)
numList = [i for i in range(10)]
for i in range(len(numList)):
if num1(numList[i]):
del numList[i]
print numList[:] #IndexError
使用列表解析可以改为:
num1 = lambda x: bool(x % 2)
numList = [i for i in range(10)]
numList[:] = [i for i in numList if not num1(i)]
print numList #[0, 2, 4, 6, 8]
6:python闭包绑定变量的误解
def creat_list():
return [lambda x: i * x for i in range(5)]
for num1 in creat_list():
print num1(2) #8 8 8 8 8
此程序的问题是因为python的延迟绑定行为导致的,就是说,任何一个返回的函数被调用时,i的值再起被调用时
在周围作用域查找,此时,循环已经完成。所以i一直都是4。
通过利用缺省参数生成匿名函数来获得期望的行为。
def creat_list():
return [lambda x, i=i: i * x for i in range(5)]
for num1 in creat_list():
print num1(2) #0 2 4 6 8
7:创建循环模块依赖
主要是在导入时,要确定某些变量是否已经被定义过,否则会导致AttributeError
问题。
8:modules与python标准库模块的命名冲突
此问题是,不能将自己的模块命名为python的标准库,否则在import时,调用相关标准库函数是无法调用的。
9:忽略了python2和python3的区别
。。。多多积累吧。
10:__del__方法的误用
'''
mod.py
'''
import foo
class Bar(object):
...
def __del__(self):
foo.cleanup(self.myhandle)
'''
another_mod.py
'''
import mod
mybar = mod.Bar() #AttributeError
原因:当解释器关闭时,模块的全局变量全部设为None,就是当__del__被调用时,foo这个名字已经被设为None。
可以使用atexit.register()
作为代替。
mod.py改为:(不是很理解。需深入学习。)
'''
mod.py
'''
import foo
import atexit
def cleanup(handle):
foo.cleanup(handle)
class Bar(object):
...
def __init__(self):
atexit.register(cleanup, self.myhandle)