本文转载自公众号《核心阅读》(ID:AI_Discovery)。代码异味是一种广泛使用的警告标志,与其字面意思相反,并不是指代码中需要立即注意的漏洞。相反,它反映了代码中更深层次的问题,更准确地说是代码中的裂缝,如果不加以纠正,可能会在未来导致更严重的后果。代码异味是弱点或设计缺陷的标志,可能导致可读性、可维护性和可扩展性方面的问题,通常是由于不良做法和未使用正确的工具造成的。Python是目前最流行的语言之一,这在很大程度上与其相当容易的学习曲线和高度伪英语的语法有关,这使得人们很容易陷入单一的做事方式。在本文中,我们将研究Python代码异味的一些典型案例以及如何避免它们。可变默认参数在Python中,使用默认参数是很常见的操作,你可以设置一个预定的值,并在调用时选择更改它。这在设置文字、数字或布尔值时很有用,因为它有助于避免带有冗余值的长参数列表。但是将可变值设置为默认参数可能很危险并会导致错误。看下面的例子:defaddElements(a=[]):a.append(5)returnaaddElements()#[5]addElements()#[5,5]同一个函数每次调用都会给出不同的结果。Python中可变默认值的问题是它们只在定义函数时被评估一次。每次调用函数时都使用变异值,可能会导致意想不到的问题,因为跟踪函数调用真的很麻烦。因此,使用None作为默认值并在函数中分配可变变量会更安全,因为您不会以可维护性问题告终,并且只有在确定需要时才使用可变默认参数。选择`range`而不是`enumerate`Python的for循环不是最常见的代码编写方式,但有时是需要的。现在,for循环在Python中的表现与在其他语言中不同,您可能会本能地以非惯用方式编写传统风格的range(len()),如下所示:names=["a","b","c"]foriinrange(len(names)):print(i,names[i])基于C风格的索引重复循环是很常见的,但这是不好的做法。它强制您通过显式索引变量访问元素,因此它不仅不是Pythonic,而且还存在可读性问题。使用枚举器提供了负责跟踪索引值和元素的元组的优势。除了更简单和更优化之外,它还提供了一个可选的第二个参数来设置值。fori,nameinenumerate(names):print(i,name)会忽略内置函数并且过度循环并非不可能,但是当在其中应用转换操作时,它会导致冗长的条件代码。在这种情况下,非常重要的是不要忽略已经可用的内置函数,例如map()filter()和reduce()。更重要的是,Python提供了列表理解,这显然是替换循环的最Pythonic方式。嵌套for循环是代码异味的另一个典型示例。Python程序员在进行模式匹配或同时运行多个迭代时很容易中枪。下面的代码多加几行就会难看:forxinlistA:foryinlistB:r.append((x,y))使用itertools不仅可以提高性能,而且更加简洁明了。看看上面的代码在itertools.product()中是多么的整洁:其他高阶函数。当同时迭代多个列表(或用于索引的枚举器)时,使用zip()函数也不错。列表推导的滥用列表推导可以灵活创建列表,功能强大,但容易被误用或滥用。让我们看一些案例。(1)在我们不需要的时候过度使用列表推导通常,我们开始着迷于使用列表推导来尝试一些奇特的东西,而不是在我们真正需要它的时候。例如,在简单的情况下,您可以使用列表构造函数:names=["A","B","C"][x.lower()forxinnames]#usethislist(map(str.lower,names))(2)使用列表推导列表推导有助于定义和创建列表,当它们实际上没有存储时,但它们总是存储在内存中。如果不使用系统进程,可能会损坏大量数据。因此,使用生成器表达式是更好的选择,因为它按需一次加载一个值。嵌套分析也需要注意,因为这会导致可读性问题,了解何时使用它以及何时退回到for循环很重要。与布尔标志参数和全局变量一样,布尔是最容易学习的数据类型。在Python中,提供命名参数让生活变得更轻松。但是,它们很容易生成带有嵌套ifelse块的复杂代码,并导致可读性问题。多个布尔值具有会产生问题的隐藏依赖关系。因此,最好使用枚举而不是多个布尔逻辑。枚举数据类型是可扩展的,并确保更好的代码结构。全局变量在所有语言中都很麻烦,Python也是如此。虽然我们有时确实需要使用它们,但将它们滥用为传递或访问数据的捷径可能很危险,因为它是可变的。跟踪它的状态可能很棘手,因为你永远不知道谁会改变它。如果你开始到处使用全局变量,命名冲突会导致命名空间受到严重影响。来源:unsplash我们都见过代码的味道,包括神秘的注释、冗余的字符串文字和幻数。编写注释时,解决“为什么”部分很重要,因为“什么”部分应该从代码本身来解释。您必须学会快速定位代码异味并将其移除。
