Python 基础——Python程序员常犯的那些错误

常见错误1:迭代时修改一个列表

删除列表中的奇数

>>>numbers = [i for i in range(10)]
>>>numbers
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

>>>odd = lambda x: bool(x%2)
>>>for i in range(len(numbers)):
...    if odd(i):
...        del numbers[i]
IndexError: list assignment index out of range

迭代时,从一个列表(List)或数组中删除元素,这是一个总所周知的错误。尽管上述程序的错误十分明显,但在开发某些大型程序时,有时则并非那么故意而为之。

幸运的是,python包含大量简洁而优雅的编程范式,若使用得当,将大大简化代码。针对上例,一个优雅的范例是通过递推式列表(list comprehensions):

>>>evens = [i for i in numbers if not odd(i)]
>>>evens
[0, 2, 4, 8]

常见错误2:滥用表达式作为函数参数的默认值

def foo(bar=[]):
    bar.append('baz')
    return bar
>>>foo()
['baz']
>>>foo()
['baz', 'baz']
>>>foo()
['baz', 'baz', 'baz']

这段代码的错误之处在于误以为:函数在没有指定形参时总是将形参设置为默认值,然而事实并非如此,对这段代码的调试以及如何使用PyCharm可参看之前的一篇文章<Python 基础——一张图告诉你PyCharm如何进行断点调试>。

正确的形式如下:

def foo(bar=None):
    if not bar:
        bar = []
        bar.append('baz')
    return bar
>>>foo()
['baz']
>>>foo()
['baz']
>>>foo()
['baz']

常见错误3:不明白闭包环境变量的绑定时机

闭包:把函数当做一个对象,因此可以作为某个函数的返回值。

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

期望输出的结果:

0
2
4
8

然而输出的结果是:

8
8
8
8
8

只是因为python的迟绑定——闭包中用到的环境变量(闭包所依赖的变量)只有在函数被调用时才会被赋值,在上述的代码中,任何时候,当返回的函数被调用时,Python会在该函数被调用时的作用域中查找i对应的值(此时循环已经结束,i被附上了最终的值4)

解决方案:

def multipliers():
    return [lambda x, i=i: i*x for i in range(5)]

>>>for multiplier in multipliers():
...    print(multiplier(2))
...
0
2
4
8

利用默认参数生成匿名函数,以实现我们想要的结果。

你可能感兴趣的:(python,常见错误)