瞧瞧,这样的「函数」才叫 Pythonic( 二 )
这一函数做两件事:计算一组关于数字列表的统计数据 , 并将它们打印到 STDOUT 。 该函数违反了只有一个原因能让函数改变的原则 。 显然有两个原因可以让该函数做出改变:新的或不同的数据需要计算或输出的格式需要改变 。 最好将该函数写成两个独立的函数:一个用来执行并返回计算结果;另一个用来接收结果并将其打印出来 。 函数有多重功能的一个致命漏洞是函数名称中含有单词「and」
这种分离还可以简化针对函数行为的测试 , 而且它们不仅被分离成一个模块中的两个函数 , 还可能在适当情况下存在于不同的模块中 。 这使得测试更加清洁、维护更加简单 。
只做两件事的函数其实非常罕见 。 更常见的情况是一个函数负责许多许多任务 。 再次强调一下 , 为可读性、可测试性起见 , 我们应该将这些「多面手」函数分成一个一个的小函数 , 每个小函数只负责一项任务 。
文档注释
很多 Python 开发者都知道 PEP-8 , 它定义了 Python 编程的风格指南 , 但很少有人了解定义了文档注释风格的 PEP-257 。 在这里并不会详细介绍 PEP-257 , 读者可详细阅读该指南所约定的文档注释风格 。
- PEP-8:
- PEP-257:
- 每一个函数都需要一个文档描述;
- 使用合适的语法和标点 , 书写完整的句子;
- 最开始需要用一句话总结函数的主要作用;
- 使用规定性的语言而不是描述性的语言 。
返回值
函数可以且应该被视为一个独立的小程序 。 它们以参数的形式获取一些输入 , 并返回一些输出值 。 当然 , 参数是可选的 , 但是从 Python 内部机制来看 , 返回值是不可选的 。 即使你尝试创建一个不会返回值的函数 , 我们也不能选择不在内部采用返回值 , 因为 Python 的解释器会强制返回一个 None 。 不相信的读者可以用以下代码测试:
? python3Python 3.7.0 (default, Jul 23 2018, 20:22:55)[Clang 9.1.0 (clang-902.0.39.2)] on darwinType "help", "copyright", "credits" or "license" *for *more information.>>> def add(a, b):... print(a + b)...>>> b = add(1, 2)3>>> b>>> b is NoneTrue
运行上面的代码 , 你会看到 b 的值确实是 None 。 所以即使我们编写一个不包含 return 语句的函数 , 它仍然会返回某些东西 。 不过函数也应该要返回一些东西 , 因为它也是一个小程序 。 没有输出的程序又会有多少用 , 我们又如何测试它呢?我甚至希望发表以下声明:每一个函数都应该返回一个有用的值 , 即使这个值仅可用来测试 。 我们写的代码应该需要得到测试 , 而不带返回值的函数很难测试它的正确性 , 上面的函数可能需要重定向 I/O 才能得到测试 。 此外 , 返回值能改变方法的调用 , 如下代码展示了这种概念:
with open('foo.txt', 'r') as input_file: for line in input_file: if line.strip().lower().endswith('cat'): # ... do something useful with these lines
代码行 if line.strip().lower().endswith('cat') 能够正常运行 , 因为字符串方法 (strip(), lower(), endswith()) 会返回一个字符串以作为调用函数的结果 。以下是人们在被问及为什么他们写的函数没有返回值时给出的一些常见原因:
「函数所做的就是类似 I/O 的操作 , 例如将一个值保存到数据库中 , 这种函数不能返回有用的输出 。 」
我并不同意这种观点 , 因为在操作成功完成时 , 函数可以返回 True 。
「我需要返回多个值 , 因为只返回一个值并不能代表什么 。 」
当然也可以返回包含多个值的一个元组 。 简而言之 , 即使在现有的代码库中 , 从函数返回一个值肯定是一个好主意 , 并且不太可能破坏任何东西 。
函数长度
函数的长度直接影响了可读性 , 因而会影响可维护性 。 因此要保证你的函数长度足够短 。 50 行的函数对我而言是个合理的长度 。
如果函数遵循单一功能原则 , 一般而言其长度会非常短 。 如果函数是纯函数或幂等函数(下面会讨论) , 它的长度也会较短 。 这些想法对于构造简洁的代码很有帮助 。
那么如果一个函数太长该怎么办?代码重构(refactor)!代码重构很可能是你写代码时一直在做的事情 , 即使你对这个术语并不熟悉 。 它的含义是:在不改变程序行为的前提下改变程序的结构 。 因此从一个长函数提取几行代码并转换为属于该函数的函数也是一种代码重构 。 这也是将长函数缩短最快和最常用的方法 。 只要适当给这些新函数命名 , 代码的阅读将变得更加容易 。
- 智能手机市场|华为再拿第一!27%的份额领跑全行业,苹果8%排在第四名!
- 会员|美容院使用会员管理软件给顾客更好的消费体验!
- 行业|现在行业内客服托管费用是怎么算的
- 人民币|天猫国际新增“服务大类”,知舟集团提醒入驻这些类目的要注意
- 国外|坐拥77件专利,打破国外的垄断,造出中国最先进的家电芯片
- 技术|做“视频”绿厂是专业的,这项技术获人民日报评论点赞
- 面临|“熟悉的陌生人”不该被边缘化
- 中国|浅谈5G移动通信技术的前世和今生
- 页面|如何简单、快速制作流程图?上班族的画图技巧get
- 桌面|日常使用的软件及网站分享 篇一:几个动态壁纸软件和静态壁纸网站:助你美化你的桌面