Python作为一种高级的动态编程语言,是出了名的容易使用。这促使它在最近几年里疯狂地流行和发展。使用的方便也伴随着误用的方便。我们把初学者在用Python写代码时可能犯的常见错误列在一起。
1.不必要的lambda表达式
在Python中,函数是一流的公民。这意味着你可以把它赋值给某个变量,在另一个函数调用中把它作为参数传递,如此等等。这对初学者或来自其他编程语言的开发者来说可能是反直觉的。
这种模式的一个常见例子是:{{< highlight python "hl_lines=4" >}} def request(self, method, **kwargs):# ... if method not in ("get", "post"): req.get_method = lambda: method.upper() # ...{{< /highlight >}}.
推荐的写法是{{< highlight python "hl_lines=4" >}} def request(self, method, **kwargs):# ... if method not in ("get", "post"): req.get_method = method.upper # ...{{< /highlight >}}。(例子)
2.提起NotImplemented
这是一个类似的命名会让开发者感到困惑的例子。NotImplementedError 是一个异常类,当派生类需要覆盖一个方法时,应该被引发。NotImplemented 是一个常数,用来实现二进制运算符。当你引发NotImplemented ,就会引发一个TypeError 。
不正确: {{< highlight python "hl_lines=3" >}} class SitesManager(object): def get_image_tracking_code(self): raise NotImplemented {{< /highlight >}}.
正确: {{< highlight python "hl_lines=3" >}} class SitesManager(object): def get_image_tracking_code(self): raise NotImplementedError {{< /highlight >}}.(例子)
3.可变的默认参数
Python中的默认参数在执行函数定义时被评估一次。这意味着表达式在定义函数时只被评估一次,并且在随后的每次调用中使用相同的值。因此,如果你在修改可变的默认参数--list,dict ,等等,它将被修改用于所有未来的调用。
错误:{{< highlight python "hl_lines=1" >}} def add_item(new_item, items=[]): items.append(new_item) {{< /highlight >}}.
正确:{{< highlight python "hl_lines=1" >}} def add_item(new_item, items=None): if items is None: items = [] items.append(new_item) {{< /highlight >}}.(例子)
4.使用assert 语句作为守护条件
由于assert 提供了一种简单的方法来检查一些条件,并使执行失败,所以开发者使用它来检查有效性是非常普遍的。但是当Python解释器用-O (优化)标志调用时,assert 语句会从字节码中删除。因此,如果在生产代码中使用assert 语句进行面向用户的验证,那么这个块根本不会被执行--可能会打开一个安全漏洞。建议只在测试中使用assert 语句。
错误:{{< highlight python >}} assert re.match(VALID_ADDRESS_REGEXP, email) is not None {{< /highlight >}}.
正确:{{< highlight python >}} 如果不是re.match(VALID_ADDRESS_REGEXP, email):提高AssertionError {{< /highlight >}}。(例子)
5.使用isinstance 代替type
type 或isinstance 都可以用来检查 Python 中对象的类型。但是有一个重要的区别--isinstance 在解析对象的类型时照顾到了继承性,而type 则没有。所以有时使用isinstance 可能不是你想用的。看一下下面的例子吧。
{{< highlight python >}} def which_number_type(num): if isinstance(num, int): print('Integer') else: raise TypeError('not an integer')
which_number(False) # 打印'Integer',这是不正确的{{< /highlight >}}。
在这里,由于bool 是Python中int 的一个子类,isinstance(num, int) 也被评估为True ,这不是预期的行为。在这种特殊情况下,使用type 才是正确的方法。在这里阅读更多关于这两种方法的行为差异。