码如其人,同学你能写一手漂亮的Python函数吗

作者:CQITer小编 时间:2018-10-15 16:35

字号
【51CTO技术沙龙第24期】10月27日,让我们共同探索AI场景化应用实现之道

与多数现代编程语言一样,在 Python 中,函数是抽象和封装的基本方法之一。你在开发阶段或许已经写过数百个函数,但并非每个函数都生而平等。写出「糟糕的」函数会直接影响代码的可读性和可维护性。那么,什么样的函数是「糟糕的」函数呢?更重要的是,要怎么写出「好的」函数呢?

Python函数

简单回顾

数学中充满了函数,尽管我们可能记不住它们。首先来回忆一下大家最喜欢的话题——微积分。你可能记得这个方程式: f(x) = 2x + 3. 这是一个叫做「f」的函数,含有一个未知数 x,「返回」2*x+3。这个函数可能和我们在 Python 中看到的不一样,但它的基本思想和计算机语言中的函数是一样的。

函数在数学中历史悠久,但在计算机科学中更加神通广大。尽管如此,函数还是存在一些缺陷。接下来我们将讨论一下什么是「好的」函数,以及在出现什么样的征兆时我们需要重构函数。

决定函数好坏的关键

好的 Python 函数与蹩脚 Python 函数的区别是什么?「好」函数的定义之多让人惊讶。从我们的目的出发,我会把好的 Python 函数定义为符合以下清单中大部分规则的函数(有些比较难实现):

命名合理

具有单一功能

包含文档注释

返回一个值

代码不超过 50 行

幂等,尽可能是纯函数

对很多人来说,这个列表可能有些过于严格。但我保证,如果你的函数符合这些规则,你的代码看起来会非常漂亮。下面我将分步讲解各个规则,然后总结这些规则如何构成一个「好」函数。

命名

关于这个问题,我最喜欢的一句话(出自 Phil Karlton,总被误以为是 Donald Knuth 说的)是:

在计算机科学中只有两个难题:缓存失效和命名问题。

听起来有点匪夷所思,但整个不错的命名真的很难。下面就有一个糟糕的函数命名:

def get_knn(from_df): 

我基本上在任何地方都见过糟糕的命名,但这个例子来自数据科学(或者说,机器学习),从业者总是在 Jupyter notebook 上写代码,然后尝试将那些不同的单元变成一个可理解的程序。

该函数命名的第一个问题是使用首字母缩写/缩略词。比起缩略词和并未普及的首字母缩写,完整的英语单词会更好。使用缩写的唯一原因是为了节省打字时间,但现代的编辑器都有自动补全功能,所以你只需键入一次全名。之所以说缩写是一个问题,是因为它们通常只能用于特定领域。在上面的代码中,knn 是指「K-Nearest Neighbors」,df 指的是「DataFrame」——无处不在的 Pandas 数据结构。如果另外一个不太熟悉这些缩写的编程人员正在阅读代码,那 TA 就会一头雾水。

关于这个函数名称,还有另外两个小问题:单词「get」无关紧要。对于大多数命名比较好的函数,很明显函数会返回一些东西,其名字会反映这一点。from_df 也是不必要的。如果参数的名称描述不够清楚的话,函数的文档注释或者类型注释将描述参数类型。

那我们如何重新命名这个函数呢?例如:

def k_nearest_neighbors(dataframe): 

现在,即使是外行也知道这个函数在计算什么了,参数的名称(dataframe)也清楚地告诉我们应该传递什么类型的参数。

单一功能原则

「单一功能原则」来自 Bob Martin「大叔」的一本书,不仅适用于类和模块,也同样适用于函数(Martin 最初的目标)。该原则强调,函数应该具有「单一功能」。也就是说,一个函数应该只做一件事。这么做的一大原因是:如果每个函数只做一件事,那么只有在函数做那件事的方式必须改变时,该函数才需要改变。当一个函数可以被删除时,事情就好办了:如果其他地方发生改动,不再需要该函数的单一功能,那么只需将其删除。

举个例子来解释一下。以下是一个不止做一件「事」的函数:

def calculate_and print_stats(list_of_numbers): 

 sumsum = sum(list_of_numbers)  

 mean = statistics.mean(list_of_numbers)  

 median = statistics.median(list_of_numbers)  

 mode = statistics.mode(list_of_numbers)  

 print('-----------------Stats-----------------')  

 print('SUM: {}'.format(sum) print('MEAN: {}'.format(mean) 

 print('MEDIAN: {}'.format(median)  

 print('MODE: {}'.format(mode) 

责任编辑:CQITer新闻报料:400-888-8888   本站原创,未经授权不得转载
关键词 >>Python 函数 代码
继续阅读
热新闻
推荐
关于我们联系我们免责声明隐私政策 友情链接