
8个实战技巧让你的程序像英文小说一样清晰流畅引言好代码的真正奥秘不在于注释而在于语言的内在优雅于软件开发这个领域当中, 我们时常会听闻这样一句话, 即“写代码应当多添加注释”。可是呢, 真正称得上编程高手的那些人心里明白, 优质的代码, 它自身便是堪称最佳的注释。我的职业经历路途里, 有那么一段堪称糟糕的过往: 有一回代码审查这事, 使得我心底懊悔到难以言表。当时面对出自自己笔下、六个月之前撰写而成的脚本, 那个脚本有足足六百行数之巨, 里头满是一层又一层相互嵌入的循环结构, 还有好似谜题谜面一般费解的条件语句, 虽说注释是处处设置存有极多, 然而其内在逻辑仍然仿若深深隐藏起面纱模样晦涩之极。就在那个瞬间, 我陡然涌起这样的认知: “这完完全全不是正常代码那种清晰模样, 简直就如同古老的象形文字一般让人费解”。打从那个时候起, 我给自身确立了一项准则, 不再去编写那种仅仅是“能用”的代码, 而是着手去编写“流畅”的代码。代码具备的流畅性, 这意味着它得以读起来好似英语那种样子, 你就几乎能够大声地把它叙述一遍。经历了多年时间当中的实践, 还有推翻以及重新去撰写, 我才终于领悟到: 其精髓, 在于并非是炫技式的那种“聪明”。本文会分享8个关键技巧, 这8个关键技巧把我的编程习惯完全改变了, 使得我的代码从“解码逻辑”转变为“阅读句子”。这些所谓的其实是“思维模式的转变”, 并非真正意义上的技巧。原因在于, 可读性强的代码本身不是教导计算机去做事, 而是朝着下一个阅读它的人含未来的你自身诠释你的想法呢。1. 让函数像“句子”一样发声语义驱动的函数命名艺术函数来进行命名, 这远远不是仅仅局限于“去使用动词”这般容易的事情。而实际上真正存在的那个诀窍, 是要使得整个函数调用的这个过程, 听起来仿佛就如同是一句完整无缺的英文对话那样。我以往常常把函数命名成 s(), 这般虽清晰, 然而欠缺叙事感, 如今, 我更偏向于从“短语”的层面去思索。错误的命名范例def calculate_user_points(points): total points return total if calculate_user_points(50) goal: # 逻辑处理流畅的命名范例def user_earns(points): total points return total请看它在实际使用中的效果if user_earns(50) goal: celebrate_victory()这一段代码, 读起来, 就好似那一句简简单单的英文, 是“如果用户赚到了50分超过了目标, 便庆祝胜利”。它基本上不太需要任何注释去说明它的作用。此处在的神奇力量并非在于语法方面, 而是在于语义层面当你出声去朗读自个之所编写出来的代码, 当于其听起来仿佛犹如明晰的指令那样之时, 那么你便已然成功跃过了蕴藏于“开发者”以及“讲述故事之人”两者之间的界缝分区区域, 这样一种负责给事物予以命名的哲学方面的思维方式, 在极大程度上削减了于未来时段当中承担维护任务之人去领会代码内部所蕴含的逻辑关系时所面对和承受的有关认知范畴之内的负担压力程度。2. 向“魔法数字”说再见, 借助Enum来提高代码“意图”呈现的可视化程度。我在早期项目里, 把用户的“角色”存成了简单整数, 比如, 代表“管理员”Admin呢是1, 代表“版主”的是2, 代表“访客”的为3, 我也许记不起那个项目, 可直到现在, 对那种数字猜谜游戏的痛苦, 我还记得一清二楚的呀。后来, 我察觉到了, 有个名为内置模块Enum, 它把那种情况彻底加以改变, 使得代码变得具备可读性。“魔法数字”范例if user.role 1: # ...使用Enum的范例from enum import Enum, auto class Role(Enum): ADMIN auto() MODERATOR auto() VIEWER auto() if user.role Role.ADMIN: grant_full_access()此时, 代码里头不存在会弄出需要去猜测状况的任何数字了。Enum所具备的作用, 是把没办法看见的含义转换成为能够看见的意图。任何去阅读这段代码的人当中的每位, 全部均可马上理解user.role所代表的业务方面应该有的确切含义带过来。专门的提示表明, 于进行枚举值定义之际, 提议运用auto()函数。如此一来, 不光能够让代码维持那种简洁的状态, 而且在你有着增添全新枚举成员需求的时候, 能够使得代码具备足够的灵活性。3. 简化重复配置利用 显式表达代码意图库当中的函数, 属于一个被极大低估了的工具, 它最关键的作用在于允准你去“冻结”一个函数的一些参数, 籍此构建出预设功能的函数。做文本清理流水线相关任务当中的时候, 我碰到过好多一遍遍重复出现那类的表达式。冗余的范例lambda text: process_text(text, lowercaseTrue, stripTrue)这般的代码, 虽说能够使用, 然而每一回瞧见, 都得开展一回“心理跳跃”, 以此去领会它的具体配置。使用 的范例from functools import partial # 创建一个预设函数将 process_text 的 lowercase 和 strip 参数固定为 True clean_text partial(process_text, lowercaseTrue, stripTrue) clean_text( Hello World! )此时, 这段代码看上去好似一条指令所说的那般: “将这段文本弄干净清理掉”把这个文本弄整洁清除掉打扫干净, 它具备极为强烈的用以表达的能力, 清楚明白简洁扼要, 毫无含糊不清之处。式子所具备的可读性, 并非在于去追求代码行数达到最少, 而是在于去追求最少数量的“心理跳跃”fewer jumps, 借助把复杂的配置隐匿在一个富有意义的变量名的后面, 达成了这一目标。4. 声明式数据结构的典范attrs让类定义如同数据宣言以往, 我在编写数据类之际, 构造函数, 常常冗长到好似一份法律合同那样, 里面充斥着巨量的自我赋值情况, 还有防御性代码。直至我碰到了attrs库, 它使得我的类定义刹那间由繁杂的“仪式”转变为简洁的数据“宣言”data, 怎么样: 它让瞬间繁琐从我的类定义变成了简洁的“宣言” data。传统的数据类简化版class User: def __init__(self, name: str, age: int, active: bool True): self.name name self.age age self.active active # 还需要手动实现 __repr__, __eq__, __hash__ 等方法...使用 attrs 的范例import attrs attrs.define class User: name: str age: int active: bool True代码量急剧地大量减少, 并且它看上去仿佛就是如同英文那般, 你并不需要去制作编写 、、等这些方法, attrs 会依据你自动地来处理这些情况, 而且呈现出的表现是完美无缺的。为何这一点极为关键重要呢? 代码等价于沟通。一旦你的类定义读起来好似结构化的语句之时, 你的心智负担就会得到减轻。你能够更为迅速地领会数据结构, 能够更为快速地开展调试, 凭借更加小的摩擦力去构建系统。它把关注点从“怎样构建对象”转到了“对象到底是什么”。5. 的叙事力量让资源管理流程化有一个处理文件的例程, 那是在几年以前, 为确保安全, 它运用了多达六个 try - 块。每一行代码都尽显“防御性”, 每一个块都散发着“偏执”的意味。接着, 我察觉到了 —— 有一个模块, 它表面看上去很安静, 然而却能够使得我的代码 “叙述一段经历”。依靠自定义上下文管理器, 我们能够以优雅的方式去处理资源的设定以及清理。使用 . 的范例from contextlib import contextmanager contextmanager def open_safely(path): # Setup阶段打开文件 f open(path, r) try: # 核心逻辑将资源 f 传出 yield f finally: # Cleanup阶段无论如何都要关闭文件 f.close() with open_safely(notes.txt) as file: read_data(file)这段with块读起来好似一段叙事, 你确切地晓得发生了何事情, 你甚至可去想象整个流程, 即是安全地将文件打开, 开展操作, 而后不管操作成功与否, 最终都会把文件关闭句号。具备可读性的代码, 并非仅仅局限于格式化方面, 而更是具体体现在关于节奏上, 那种节奏赋予了你的代码一种呼吸感, 使得复杂的资源管理逻辑, 变得恰似流水线一般顺畅。6. 使用 提升循环的“描述性”我曾经有过一回“尴尬”的经历, 为了在组合项目里的成对元素的这事上, 我不得已进行了嵌套, 而且是嵌套了三个循环, 这样的代码被戏谑地称作“循环嵌套地狱”loop-。经过一番探寻, 我察觉到了那个库, 它使我领会到, 我能够径直地“表述出我的想法”, 而非依靠手动去撰写繁杂的循环逻辑。假设你需要生成所有颜色和尺寸的组合。“循环嵌套地狱”范例colors [red, blue] sizes [S, M, L] for color in colors: for size in sizes: print(color, size)虽然这段代码只有两层循环但想象一下更复杂的组合需求。使用 . 的范例from itertools import product colors [red, blue] sizes [S, M, L] for color, size in product(colors, sizes): print(color, size)这时, 我所读取到的已然并非那晦涩难懂的“循环嵌套”了, 而是呈现出清晰模样的这般描述: “针对每一个颜色以及尺寸”for every color and size。这属于一个故事, 并非是一个循环。在代码结构能够精准映射至你思维进程之际, 开展代码推导与推理便会变得毫无困难。众多高级迭代器函数亦被提供, 比方说组合、排列等, 这些借由清晰命名替换了繁杂手动循环实现, 显著增强了代码描述性。7. 让你的自动化程序具备“语法”感知能力这个技巧可能纯粹是为了乐趣但它在很多场景下却出奇地有用。你有没有碰到过自动化脚本打印出存在语法错误的句子呀? 比如说, 我的一个报告工具曾经打印出了让人尬尴的信息:存在那样的情况, 有三个, 是那种状态, 有三个, 具备那样的情形, 有三个。此刻, 库就现身了。它是一种小众却精妙的工具, 能使借助机器产出的文字听上去有人类语言的感觉。使用 的范例import inflect p inflect.engine() count 3 # p.plural_verb(is, count) 根据 count 确定动词的单复数形式 # p.plural(error, count) 根据 count 确定名词的单复数形式 print(fThere {p.plural_verb(is, count)} {count} {p.plural(error, count)}.) # 输出: # There are 3 errors.这并非单纯只是“可爱”或者“有趣”, 它和清晰度相关。有这样一个系统, 是自动化且能够像你一样进行说话的系统, 其往往更易于维护, 并且更值得被信赖。在用户界面当中, 在日志记录里面, 在报告生成方面, 要把那些细微的语法错误得以消除, 可以极大去提升软件所具备的专业性以及可读性。8. “叙事性”管道 技巧从上到下的命令序列伴随着我编写的代码数量不断增多, 我愈发强烈地意识到这样一个真理, 那就是, 最好的代码, 应当如同一套指令那般, 依照从上至下的顺序被阅读。通过进行链式函数调用, 返回包含丰富上下文的数据, 以此来“伪造”出一种“叙事性管道”, 这种模式, 会把整个程序流程转变为一个清晰的命令序列。理想当中的那种, 可称作“叙事性管道”的模式, 此模式会用到一种目前尚不支持的, 名为 | 的运算符。def load_data(path): ... # 加载数据 def clean(data): ... # 清理数据 def analyze(data): ... # 分析数据 def report(results): ... # 报告结果 ( load_data(dataset.csv) | clean | analyze | report )虽其尚未在原生状态下对|管道运算符予以支持可, 然则我们能够借由一个简易的辅助类去模拟这般效果:使用 Pipe 类模拟管道操作符class Pipe: def __init__(self, value): self.value value # 重载 | 运算符使其表现为函数调用并将结果传递给下一个 Pipe 实例 def __or__(self, func): return Pipe(func(self.value)) def __repr__(self): return repr(self.value) Pipe(dataset.csv) | load_data | clean | analyze | report此时, 这段代码已不再是一个个各自独立的函数调用, 而是转变为一串命令序列。它不但极富表达力, 并且即便读起来, 也恰似一个清晰的流程。它以代码的形态讲述了一整个完整的故事: 进行加载数据的操作, 接着清理数据, 随后分析数据, 最后生成报告。这样一种从顶部到底部的逻辑流, 使得复杂的批处理或者数据处理脚本变得格外清晰。终极思考从“能用”到“流畅”一次思维模式的跃迁每位开发者, 迟早定然会碰到那堵墙, 什么墙, 代码是能够运行的, 然而却感觉不太对劲, 这便是我多年前所处的状况, 至于现在, 我所编写的代码, 已然能够按照我思考的那种方式被阅读了。犹如之前所讲述的那般, 本文予以分享的那八点内容, 并非如同具体的“技巧”展现出来的样子, 反而像是“思维模式形成的转变”这般。具有可观读性的代码, 其关键核心并非是要教会计算机怎样去开展工作, 而是在于朝着未来会阅读它的人其中涵盖未来的你自己说明白你的思考具体过程。艾伦·佩利斯Alan 曾说过一句经典名言一门, 不影响, 你对编程的, 那份的想法的, 观念的, 那个样子的, 那种思绪的, 这类思考方式的, 这么一种方式感的途径的语言, 不值得去进行学习。深入掌握这门语言要领会其精髓, 深入掌握这门语言不只是让你将为比之前优秀的编码员更具突出性增强一些自己所具备的能力, 深入掌握这门语言更是会让你成为比较之前更优秀的思考者拥有提升。它不得不迫使约束你以更明朗清楚、更有传达能力力度的方式来把你的逻辑做出条理化的安排组织倘若你把这篇文章读完, 进而着手重新思索你所编撰的方式, 那么就在今晚开启对一个你近期所撰写的函数予以重构, 试着使它读起来与英文那般顺畅, 你将会即刻体会到那种本质层面的差异。当再度审阅那段代码的是你未来的自己之时, 并且不由自主地露出微笑之际——恭喜你, 你已然做对了。代码所呈之艺术, 最终归属语言之艺术。附八个关键技巧总结