我个人对陷阱的定义是这样的:代码看起来可以工作,但不是以你“想当然“”的方式。如果一段代码直接出错,抛出了异常,我不认为这是陷阱。比如,Python程序员应该都遇到过的“
UnboundLocalError”, 示例:
对于
“
UnboundLocalError”,还有更高级的版本:
可能对于很多python新手来说,这个Error让人摸不着头脑。但我认为这不算陷阱,因为这段代码一定会报错,而不是默默的以错误的方式运行。不怕真小人,就怕伪君子。我认为缺陷就好比伪君子。
那么Python中哪些真正算得上陷阱呢?
第一:以mutable对象作为默认参数
这个估计是最广为人知的了,Python和其他很多语言一样,提供了默认参数,默认参数确实是个好东西,可以让函数调用者忽略一些细节(比如GUI编程,Tkinter,QT),对于lambda表达式也非常有用。但是如果使用了可变对象作为默认参数,那么事情就不那么愉快了。
惊喜不惊喜?!究其原因,python中一切都是对象,函数也不列外,默认参数只是函数的一个属性。而默认参数在函数定义的时候已经求值了。
python docoment 给出了标准的解决办法:
第二: x += y vs x = x + y
一般来说,二者是等价的,至少看起来是等价的(这也是陷阱的定义 — 看起来都OK,但不一定正确)。
被光速打脸了?
前者x指向一个新的对象,后者x在原来的对象是修改,当然,那种效果是正确的取决于应用场景。至少,得知道,二者有时候并不一样
第三,神奇的小括号–()
小括号(parenthese)在各种编程语言中都有广泛的应用,python中,小括号还能表示元组(tuple)这一数据类型, 元组是immutable的序列。
但如果只有一个元素呢
神奇不神奇,如果要表示只有一个元素的元组,正确的姿势是:
第四:生成一个元素是列表的列表
这个有点像二维数组,当然生成一个元素是字典的列表也是可以的,更通俗的说,
生成一个元素是可变对象的序列
很简单嘛:
看起来很不错,简单明了,but
我猜,这英国不是你预期的结果吧,究其原因,还是因为python中list是可变对象,上述的写法大家都指向的同一个可变对象,正确的姿势
第五,在访问列表的时候,修改列表
列表(list)在python中使用非常广泛,当然经常会在访问列表的时候增加或者删除一些元素。比如,下面这个函数,试图删掉列表中为3的倍数的元素: