Python中常见的初学者错误

116 阅读2分钟

Python作为一种高级的动态编程语言,是出了名的容易使用。这促使它在最近几年里疯狂地流行和发展。使用的方便也伴随着误用的方便。我们把初学者在用Python写代码时可能犯的常见错误列在一起。

1.不必要的lambda表达式

在Python中,函数是一流的公民。这意味着你可以把它赋值给某个变量,在另一个函数调用中把它作为参数传递,如此等等。这对初学者或来自其他编程语言的开发者来说可能是反直觉的。

这种模式的一个常见例子是:

def request(self, method, **kwargs):
    # ...
    if method not in ("get", "post"):
        req.get_method = lambda: method.upper()
    # ...

推荐的写法是:

def request(self, method, **kwargs):
    # ...
    if method not in ("get", "post"):
        req.get_method = method.upper
    # ...

2.提起NotImplemented

这是一个类似的命名会让开发者感到困惑的例子。NotImplementedError 是一个异常类,当派生类需要覆盖一个方法时,应该被引发。NotImplemented 是一个常数,用来实现二进制运算符。当你引发NotImplemented ,就会引发一个TypeError

不正确:

class SitesManager(object):
    def get_image_tracking_code(self):
        raise NotImplemented

正确:

class SitesManager(object):
    def get_image_tracking_code(self):
        raise NotImplementedError

3.可变的默认参数

Python 中的默认参数在执行函数定义时被评估一次。这意味着表达式在定义函数时只被评估一次,并且在以后的每次调用中使用相同的值。因此,如果你在修改可变的默认参数--list,dict ,等等,它将被修改用于所有未来的调用。

不正确:

def add_item(new_item, items=[]):
    items.append(new_item)

正确:

def add_item(new_item, items=None):
    if items is None:
        items = []
    items.append(new_item)

4.使用assert 语句作为守护条件

由于assert 提供了一种简单的方法来检查一些条件并使执行失败,所以开发者使用它来检查有效性是非常普遍的。但是当Python解释器用-O (优化)标志调用时,assert 语句会从字节码中删除。因此,如果在生产代码中使用assert 语句进行面向用户的验证,那么这个块根本不会被执行--可能会打开一个安全漏洞。建议只在测试中使用assert 语句。

不正确:

assert re.match(VALID_ADDRESS_REGEXP, email) is not None

正确:

if not re.match(VALID_ADDRESS_REGEXP, email):
    raise AssertionError

5.使用isinstance 来代替type

typeisinstance 都可以用来检查 Python 中一个对象的类型。但是有一个重要的区别--isinstance 在解决对象的类型时照顾到了继承性,而type 则没有。所以有时使用isinstance 可能不是你想用的。看一下下面的例子:

def which_number_type(num):
    if isinstance(num, int):
        print('Integer')
    else:
        raise TypeError('Not an integer')

which_number(False)  # prints 'Integer', which is incorrect

在这里,由于bool 是 Python 中int 的一个子类,isinstance(num, int) 也被评估为True ,这不是预期的行为。在这种特殊情况下,使用type 是正确的方法。在这里阅读更多关于这两种方法的行为差异。