怎样写一个更好的Python函数?
副问题[/!--empirenews.page--]
Python固然好用,但用好真的很难。 尤其是函数部门,只要写欠好,后头的陆续串人城市遭殃。 看又看不懂,测试起来也贫困,维护又维护不动,真是让人头疼。 那怎么写好一个Python函数呢? 《Writing Idiomatic Python》一书的作者在Medium上颁发了一篇文章,给出了6个提议。 但愿可以或许给你带来辅佐。 什么样的函数是一个好函数? “好”的Python函数和“差”的Python函数之间有什么不同呢?每小我私人都有本身的领略。基于我的领略,假如一个Python函数可以或许切合下面的大部门前提,我会以为它是一个“好”函数: 定名公道 单一成果 包罗文档字符串 返回一个值 不高出50行 是幂等函数或纯函数 对很多人来说,这些要求也许显得过于苛刻了。 不外,我担保,假如你的函数遵循这些法则,你的代码会很是大度,会让其他的措施员都“馋哭”的。 下面,我将逐一接头这些法则,然后总结它们是怎样缔造“好”函数的。 定名 在这个题目上,我最喜好的一句话是: 计较机科学中只有两件事很让人头疼:缓存失效和定名。 尽量这听起来很莫名其妙,但给一个工作定名太难了。下面是一个后面案例: defgetknn(from_df): 原文中这个代码没有放上去,量子位按照上下文信息举办了增补。 这个函数定名的第一个题目是它行使了缩写。 对付那些并不着名的缩略词来说,行使完备的英语单词会更好。缩写单词的独一缘故起因是为了节减打字时刻,可是每个当代编辑器都有自动添补成果,以是你只必要键入一次全名就可以了。 缩写凡是是特定规模的。在上面的代码中,KNN指的是“K-Nearest Neighbors”,df指的是“DataFrame”,这是一个数据布局。假如另一个不认识这些首字母缩写的措施员正在阅读代码,险些很丢脸懂。 关于这个函数的名字尚有其它两个小瑕疵: “get”这个词是无关紧急的。对付大大都定名较量好的函数来说,很明明有一些对象会从函数中返回,它的名字将反应这一点。 from_df也不是须要的。假如没有明晰的参数名称,函数的文档字符串或范例注释会描写参数的范例。 那么我们怎样重定名这个函数呢?很简朴: defk_nearest_neighbors(dataframe): 纵然是生手,这个函数要计较的内容也很清晰,参数的名称(dataframe)也清晰地表白了参数范例。 单一成果 单一成果原则不只合用于类和模块,也同样合用于函数。 一个函数应该只有一个成果。也就是说,它应该只做一件事。 一个重要的缘故起因是,假如每个函数只做一件事,只有这件事产生了变革,才必要改变这个函数。 另外,假如这个函数的单个成果不再必要了,直接把它删了就行了。 照旧用例子来声名吧。下面这个函数,可以做不止一件“工作”: defcalculate_andprint_stats(list_of_numbers): sum = 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) 这个函数做了两件事:一是计较一组关于数字列表的统计数据,二是将它们打印到STDOUT。 假如必要计较新的或差异的统计数据,可能必要改变输出的名目,就必要对这个函数举办调解。 以是,这个函数最好写成两个独立的函数:一个用来执行并返回计较功效,另一个用来获取这些功效并打印出来。 这种处理赏罚方法,不只能让测试函数更轻易,而且还应承这两个部门有了迁徙性,假如吻合的话,还也许一路应用到差异的模块中。 在编程中,你会发明许多几何函数都可以做许多许多工作。同样,为了可读性和可测试性,这些函数应该被解析成更小的函数,每个函数只有一个成果。 文档字符串(Docstrings) 固然每小我私人好像都知道PEP - 8,它界说了Python的样式指南,可是很少有人知道PEP - 257,它是关于文档字符串的。我再这里不简朴地一再PEP - 257的内容了,你可以在闲暇时读一下。个中的要害内容是: 每个函数都必要有一个文档字符串 行使恰当的语法和标点标记;用完备的句子写 起首对函数的浸染举办一句话的总结 行使声名性说话而不是描写性说话 在编写函数时,要养成写文档字符串的风俗,并在编写函数代码之前实行写一下。 假如你不能写一个清楚的文档字符串来描写函数做什么,就声名你必要再思量思量为什么要写这个函数了。 返回值 函数可以被以为是一些独立的措施。它们以参数的情势接管一些输入,并返回一些功效。 参数有没有都可以,但从Python内部的角度来看,返回值是必必要有的。你不行能建设一个没有返回值的函数。假如函数没有返回值,Python会“逼迫”返回None。你可以测试一下这段代码: ? python3 Python3.7.0(default, Jul232018,20:22:55) [Clang9.1.0(clang-902.0.39.2)] on darwin Type"help","copyright","credits"or"license"formore information. >>>defadd(a, b): ... print(a + b) ... >>> b = add(1,2) 3 >>> b >>> bisNone True 你会发明 b 的返回值现实上是 None。 纵然你写的函数没有返回语句,它如故会返回一些对象。并且,每个函数都应该返回一个有效的值,测试起来也会更利便。事实,你写的代码应该可以或许被测试。 试想一下,测试上面的add函会有多艰巨。遵循这个观念,我们应该这样写代码: withopen('foo.txt','r')asinput_file: forlineininput_file: ifline.strip().lower().endswith('cat'): # ... do something useful with these lines if line.strip().lower().endswith(‘cat’):这一行可以或许事变,是由于每个字符串要领( strip ( )、lower ( )、end swith ( ) )都返回一个字符串作为挪用函数的功效。 当给定函数没有返回值时,有一些常见的缘故起因: “它所做的只是[一些与I / O相干的工作,好比将一个值生涯到数据库中]。我不能返回任何有效的对象。” 我差异意。假如操纵顺遂完成,函数可以返回True。 “我们修改了个中一个参数,将其用作参考参数。” 这里有两点必要留意。起首,尽最大全力停止这种做法。用好了令人惊奇,用欠好很是伤害。 其次,纵然这样做不行行,复制某个参数的本钱太高,你也可以回到上一条提议。 “我必要返回多个值。单独返回一个值是没故意义的。” 可以行使元组返回多个值。 老是返回一个有效的值,挪用者老是可以自由地忽略它们。 函数长度 让你读一个200行的函数,并说出它是做什么的,你是什么感觉? 函数的长度直接影响可读性,从而影响可维护性。以是要保持你的函数简短。50行是一个随意的数字,在我看来是公道的。你编写的大大都函数应该要短一些。 假如一个函数遵循单一成果原则,它很也许是相等短的。 假如它是纯函数或是幂等的(下面接头) ,它也也许是短的。 那么,假如函数太长,应该怎么做?重构。这会改变措施的布局而不改变其举动。 从一个长函数中提取几行代码,并把它们酿本钱身的函数。这是收缩长函数的最快、也是最常见的方法。 加上你给全部这些新函数取了吻合的名称,因今天生的代码读起来也会更轻易。 幂等和函数纯度 不管被挪用了几多次,幂等函数老是在给定沟通参数集的环境下返回沟通的值。 功效不依靠于非局部变量、参数的可变性或来自任何I / O流的数据。下面的这个add_three(number)函数是幂等函数: 不管一小我私人挪用add_three(7)几多次,谜底老是10。以下是一个非幂等函数: defadd_three(): """Return 3 + the number entered by the user.""" number = int(input('Enter a number: ')) returnnumber +3 这个函数的返回值取决于I / O,即用户输入的数字。对add_three()的每次挪用城市返回差异的值。 假如它被挪用两次,用户可以第一次输入3,第二次输入7,别离挪用add_three()返回6和10。 幂等性的一个实际中例子是在电梯前点击“向上”按钮。第一次定时,电梯会被“关照”你要上去。由于按按钮是幂等的,以是重复按它都没有什么影响。功效是一样的。 为什么幂等很重要? 可维护性和可维护性。幂等函数很轻易测试,由于在行使沟通的参数时,它们老是返回沟通的功效。 测试仅仅是搜查通过差异挪用返回值的预期值。更重要的是,这些测试很快,这是单位测试中一个重要且常常被忽视的题目。 而在处理赏罚幂等函数时,重构是垂手可得的工作。 无论如安在函数之外变动代码,行使沟通的参数挪用它的功效老是一样的。 什么是纯函数? 在函数编程中,假如一个函数既幂等又没有可调查到的副浸染,它就被以为是纯函数。函数外部的任何对象都不会影响这个值。 (编辑:湖南网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |