编写干净的,Python式的代码就是要尽可能地使其易于理解,但又要简明扼要。以下是有关Python重构的系列文章的第二部分,第一部分见Python代码重构(一)。本系列的重点是为什么这样做是好的做法,而不仅仅是教你如何做。编码的时候我们经常要创建集合。在大多数语言中,标准的做法如下: values = [] 在这里我们创建一个数据集列表values,用数字迭代的填充它。在Python中,我们可以访问列表生成式。这样可以在一行上做相同的事情,消除了声明一个空列表然后赋值的麻烦:
我们已经将三行代码转换为一行代码,这绝对是一种胜利——这意味着在阅读方法时减少了来回滚动,并有助于保持代码的可管理性。 将代码压缩到一行可能会更难以阅读,但对于理解来说并非如此。需要的所有元素都很好地呈现出来,并且一旦习惯了这种语法,它实际上比for循环版本更具可读性。 另一点是,赋值现在更像是一个原子操作——我们在声明什么是values,而不是提供关于如何构建它的说明。这使代码读起来更像是一种叙述,因此今后我们更关注values是什么,而不是它的构造细节。 最后,列表生成式的执行通常比在循环中构建集合更快,这是另一个考虑性能的因素。 增强赋值是Python的一个简便语法,比如下面的代码 count = count + other_value 可以替换成下面的代码:
这样代码更短更清晰——我们不需要两次考虑count变量。其他可以使用的操作符包括-=、*=、/=和**=。需要注意的一点是,要赋值的类型必须定义适当的操作符。例如,numpy数组不支持/=操作。 在代码中经常看到给结果变量赋值,然后立即返回它。 def method(self): 这里最好直接返回结果
这缩短了代码并删除了一个不必要的变量,减少了读取函数的心理负担(mental load)。 临时变量可能有用的地方是,如果它们被用作参数或条件,名称可以当做变量所代表的内容的注释。在从函数返回它的情况下,函数名告诉你结果是什么——在上面的例子中,它是状态属性,而state名没有提供任何额外的信息。 根据某些程序状态,通常需要将一个变量设置为两个不同值中的一个。 if condition: 可以使用Python的条件表达式语法(它的三元操作符版本)将其写在一行上:
这肯定更简洁,但它是最有争议的重构之一(也包括列表推是)。一些程序员不喜欢这些表达式,并且发现解析它们比完全写出它们要稍微难一些。 我们的观点是,只要条件表达式很短,并且适合在一行中,它就是一种改进。只有一条语句定义了x,而不是必须读取两个语句加上if-else行。 一个小技巧是像any、all和sum这样的函数允许传入生成器而不是集合。这意味着与其这样做: hat_found = any([is_hat(item) for item in wardrobe]) 你可以这样写:
上述代码删除了一对括号,使意图更加清晰。如果找到了hat,它将立即返回,而不必构建整个列表。这种延迟计算可以提高性能。 请注意,我们实际上是在向any()传递一个生成器,所以严格地说,代码应该是这样的: hat_found = any((is_hat(item) for item in wardrobe)) 但是Python允许忽略这对括号。接受生成器的标准库函数有:
最后一个重构是我们希望一个方法的末尾返回True或False。一种常见的方法是这样的:
然而,像这样直接返回结果会更简洁: def function(): 只有当表达式的计算结果为布尔值时才能执行此操作。在这个例子中:
我们不能进行这种精确的重构,因为现在我们可以返回hats的列表,而不是True或False。为了确保返回的是一个布尔值,可以调用bool()来包装返回值: def any_hats(): |
|