- Preface 前言
- 第1章 引论
- 第2章 编程惯用法
- 第3章 基础语法
- 建议19:有节制地使用 from…import 语句
- 建议20:优先使用 absolute import 来导入模块
- 建议21:i+=1 不等于 ++i
- 建议22:使用 with 自动关闭资源
- 建议23:使用 else 子句简化循环(异常处理)
- 建议24:遵循异常处理的几点基本原则
- 建议25:避免 finally 中可能发生的陷阱
- 建议26:深入理解 None 正确判断对象是否为空
- 建议27:连接字符串应优先使用 join 而不是 +
- 建议28:格式化字符串时尽量使用 .format 方式而不是 %
- 建议29:区别对待可变对象和不可变对象
- 建议30:[]、() 和 {}:一致的容器初始化形式
- 建议31:记住函数传参既不是传值也不是传引用
- 建议32:警惕默认参数潜在的问题
- 建议33:慎用变长参数
- 建议34:深入理解 str() 和 repr() 的区别
- 建议35:分清 staticmethod 和 classmethod 的适用场景
- 第4章 库
- 建议36:掌握字符串的基本用法
- 建议37:按需选择 sort() 或者 sorted()
- 建议38:使用 copy 模块深拷贝对象
- 建议39:使用 Counter 进行计数统计
- 建议40:深入掌握 ConfigParser
- 建议41:使用 argparse 处理命令行参数
- 建议42:使用 pandas 处理大型 CSV 文件
- 建议43:一般情况使用 ElementTree 解析 XML
- 建议44:理解模块 pickle 优劣
- 建议45:序列化的另一个不错的选择 JSON
- 建议46:使用 traceback 获取栈信息
- 建议47:使用 logging 记录日志信息
- 建议48:使用 threading 模块编写多线程程序
- 建议49:使用 Queue 使多线程编程更安全
- 第5章 设计模式
- 第6章 内部机制
- 建议54:理解 built-in objects
- 建议55:init() 不是构造方法
- 建议56:理解名字查找机制
- 建议57:为什么需要 self 参数
- 建议58:理解 MRO 与多继承
- 建议59:理解描述符机制
- 建议60:区别 getattr() 和 getattribute() 方法
- 建议61:使用更为安全的 property
- 建议62:掌握 metaclass
- 建议63:熟悉 Python 对象协议
- 建议64:利用操作符重载实现中缀语法
- 建议65:熟悉 Python 的迭代器协议
- 建议66:熟悉 Python 的生成器
- 建议67:基于生成器的协程及 greenlet
- 建议68:理解 GIL 的局限性
- 建议69:对象的管理与垃圾回收
- 第7章 使用工具辅助项目开发
- 第8章 性能剖析与优化
建议79:了解代码优化的基本原则
代码优化是指在不改变程序运行结果的前提下使得程序运行的效率更高,优化的代码意味着运行速度更快或者占有的资源更少。进行代码优化时需要记住以下几点原则。
(1)优先保证代码是可工作的
Donald Knuth曾说过,过早优化是编程中一切“罪恶”的根源。很多人热衷优化,一开始写代码就奔着性能这个目标。但事实真相是“让正确的程序更快要比让快速的程序正确容易得多。”因此优化的前提是代码满足了基本的功能需求,是可工作的。过早地进行优化可能会忽视对总体性能指标的把握,忽略可移植性、可读性、内聚性等,更何况每个模块甚至每行优化的代码并不一定能够带来整体运行性能良好,因为性能瓶颈可能出现在意想不到的地方,如模块与模块之间的交互和通信等,在得到整体视图之前不要主次颠倒。需要说明的是,这并不是不鼓励你在代码实现的过程中去尝试更优的实现方式,在编码的过程中同样应该遵循Python的哲学和本书前面章节所提倡的风格与语法,尽量选择更好的算法或者实现。
(2)权衡优化的代价
优化是有代价的,想解决所有性能问题几乎是不可能的。从代码本身的角度来讲,可能面临着牺牲时间换空间或者牺牲空间换时间的抉择;从项目的角度来讲,质量、时间和成本这三者之间“铁三角”关系不会改变,如果性能是权衡质量的一个指标的话,更好的性能意味着需要更多的时间和人力或者更强大的硬件资源;从用户的角度来看,根据80/20法则,最终影响用户体验的可能也就是20%的性能问题。因此,优化需要权衡代价,如果在项目时间紧迫的情况下能够仅仅通过增加硬件资源就解决主要性能问题,不妨选择更强大的部署环境;或者在已经实现的代码上进行修修补补试图进行优化代码所耗费的精力超过重构的代价时,重构可能是更好的选择。
(3)定义性能指标,集中力量解决首要问题
你可能曾经听到过客户这样的声音:我希望这个功能反应更快一点。这很好,起码你明白优化的目标所在,而不至于像个“无头苍蝇”一样抓不住客户需要的方向而导致最后落个费力不讨好的结果。但这还不够好,为什么?什么标准才符合更快一点这个说法呢?更快到底是多快?“一千个人心中就有一千个哈姆雷特”,我们必须制定出可以衡量快的具体指标,比如在什么样的运行环境下(如网络速度、硬件资源等)、运行什么样的业务响应时间的范围是多少秒。这里要着重强调的是:精确,可度量。更快、非常快这些都是描述性的词语,并不可度量,不同的人有着不同的衡量标准,可能对于一个请求你认为2秒内能够返回结果已经够快了,但业务人员所理解的够快可能是0.5秒内,偏差由此产生。如果你的客户并不能提出专业精确的目标,那么相关需求人员或者技术人员也一定要引导和帮助客户(如运用SMART法则等)最终达成契约。另外,性能优化一定要站在客户和产品本身的角度上分析而不是开发人员的角度上。为什么?因为客户才是我们服务的主要对象,他们的想法才能代表最终的需求。比如开发人员可能觉得安装的时间过长而花费不少精力进行优化,但客户真正关心的可能是在系统上部署一个新的服务的响应时间。因此,在进行优化之前,一定要针对客户关心的问题进行主次排列,并集中力量解决主要问题。
(4)不要忽略可读性
优化不能以牺牲代码的可读性,甚至带来更多的副作用为代价。实际应用中经常运行的代码可能只占一小部分,但几乎所有代码都是需要维护的,因此在代码的可读性、可维护性以及更优化的性能之间需要权衡。如果优化的结果是使代码变得难以阅读和理解,可能停止优化或者选择其他替代设计更好。
最后需要说明的是,优化无极限,不要陷入怪圈,什么时候应该优化、什么时候应该停止优化心里得有谱,性能较优的代码确实很吸引人,但过犹不及。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论