【AICon】AI 基础设施、LLM运维、大模型训练与推理,一场会议,全方位涵盖! >>> 了解详情
写点什么

怎样让你写的 Python 代码更优雅?

  • 2020-04-03
  • 本文字数:4125 字

    阅读完需:约 14 分钟

怎样让你写的Python代码更优雅?


通常,当我们在学校学习时,编程美学不是一个关键问题。用 Python 写代码时,个人也会遵循自己的风格。然而,当我们必须花大把时间来理解一个人的隐式代码时,这项工作肯定不受欢迎,这种情况同样可能发生在别人阅读我们的代码时。所以,让我们聚焦 Python 之禅和一些改进技巧,从而解决问题。

Python 之禅?

对于此前没听说过的人,请在 Python 解释器中键入并执行import this,会出现由 Tim Peters 撰写的 19 条指导原则:


  1. 优美胜于丑陋;

  2. 明了胜于晦涩;

  3. 简单胜于复杂;

  4. 复杂胜于晦涩;

  5. 扁平胜于嵌套;

  6. 间隔胜于紧凑;

  7. 可读性很重要;

  8. 特例不足以特殊到违背这些原则;

  9. 实用性胜过纯粹;

  10. 永远不要默默地忽视错误;

  11. 除非明确需要这样做;

  12. 面对模棱两可,拒绝猜测;

  13. 解决问题最直接的方法应该有一种,最好只有一种;

  14. 可能这种方法一开始不够直接,因为你不是荷兰人;

  15. 做也许好过不做;

  16. 但不想就做还不如不做;

  17. 如果方案难以描述明白,那么一定是个糟糕的方案;

  18. 如果实现容易描述,那可能是个好方案;

  19. 命名空间是一种绝妙的理念,多加利用!


在这篇文章中,我将分享自己对这些格言的理解以及我学到的一些有用的 Python 技巧。

优美胜于丑陋

Python 具有语法简单、代码可读性强和命令类似英语等特点,这让编写 Python 代码比使用其他编程语言更容易、更高效。例如,使用or and|| &&构建语义相同的表达式:


# &&, ||if a == 0 && b == 1 || c == True:  # and, orif a == 0 and b == 1 or c == True:  # 这两个逻辑表达式在Python中是相同的# 从语义的角度来看,可以使用选择操作符来构造完全相同的表达式。
复制代码


此外,代码的布局和组成非常重要,有大量资源涉及这个主题。下面是最受欢迎也是我最喜欢的一个:PEP 8——Python代码风格指南


浏览完 PEP8 后,看看下面这些文章,其中展示了一些亮点和应用:



永远不要弄乱你的代码。要优雅而美丽。

明了胜于晦涩

在 Python 中,良好的命名约定不仅可以提升你的课堂成绩,而且还能让你的代码更明了。幸运的是,你能在PEP8中找到一些指导原则,我想在下面强调其中的一些要点。


  • 一般来说,避免使用以下名称:


  1. 太宽泛,如my_list

  2. 太冗长,如list_of_machine_learning_data_set

  3. 太模糊,如“1”、“I”、“o”、“O”。


  • 包/模块名应该全部小写:


  1. 首选使用一个单词命名;

  2. 当需要使用多个单词时,使用下划线分割它们。


  • 类名应遵循 UpperCaseCamelCase 规范

  • 变量\方法\函数应该采用小写(如果需要,用下划线分割)

  • 常量名必须全大写(如果需要,用下划线分割)


一切都必须清晰易懂。

简单胜于复杂

简单比复杂更难:你必须付出巨大艰辛,化繁为简。但这一切到最后都是值得的,因为一旦你做到了,你便能创造奇迹。——乔布斯


很多时候,在处理迭代器时,我们还需要保存迭代计数。Python 通过提供一个名为enumerate()的内置函数简化这一任务。以下是一种不成熟的方法,然后是推荐方法:


words = ['Hannibal', 'Hanny', 'Steeve']# 不成熟的方法index = 0for word in words:    print(index, word)    index += 1    # 推荐方法for index, word in enumerate(words):    print(index, word)
复制代码


另一个示例是使用内置的zip()函数,该函数创建一个迭代器,对来自两个或多个迭代器的元素进行配对。你可以使用它来快速有效地解决常见的编程问题,比如创建字典。


subjects = ['math', 'chemistry', 'biology', 'pyhsics']grades = ['100', '83', '90', '92']grades_dict = dict(zip(subjects, grades))print(grades_dict)
复制代码


化繁为简的能力就是消除不必要的东西,保留必要的东西。

复杂胜于晦涩

复杂(complex )和晦涩(complicated )的区别在于,复杂是指组件的系统层级,晦涩是指难度高。


有时候,尽管我们试图让任务变得简单和傻瓜化,结果可能仍然很糟。在这种情况下,编程优化变得很有必要,我最喜欢的学习方法是完成coding challenge websites上的工作。你可以查看其他人的解决方案,甚至能受到更好算法的启发。


对于入门,HackerRank提供了适合新手程序员的各种级别任务,这非常棒。之后,可以去尝试更专业的网站,比如CoderbyteTopcoder

扁平胜于嵌套

嵌套模块在 Python 中并不常见——至少我之前没有见过像module.class.subclass.function这样的东西——可读性不好。虽然在另一个子模块中构建子模块可能会减少代码行数,但我们不希望用户被不直观的语法所困扰。

间隔胜于紧凑

不要在一行中插入太多代码,这会给读者带来压力。建议最大行长度 79 个字符。这样,当使用代码评审工具时,编辑器窗口宽度限制才能很好工作。



使用 Python 从 Unsplash 下载图片

可读性很重要

代码的阅读次数比编写次数多。考虑下缩进,它让代码更容易阅读,比较下面的代码:


money = 10000000print("I earn", money, "dollars by writing on medium.")
money = 10_000_000print(f"I earn {money} dollars by writing on medium.")
复制代码


在本例中,代码结果相同,但是后一段代码通过使用下划线占位符和 f-string 提供了更好的可读性。在 Python 3.6 发布后,f-string 开始让格式化变得更简单,并且在处理包含更多变量的更长的句子时更强大。


一个作家的风格不应该在他的思想和读者的思想间设置障碍。

特例不足以特殊到违背这些原则

关键是为一般情况提供一贯支持,尝试将一个繁琐的项目重新组织成一个简单形式。例如,根据其功能,结构化类的代码或将其分类到不同的文件中,即使 Python 并不强迫你这样做。由于 Python 是一种多范式编程语言,解决问题的一个强大方法是创建对象,这就是所谓的面向对象编程


面向对象编程是一种组织程序结构的编程范式,让属性和行为可以被看作是单独对象。它的优点是直观和易于操作,许多教程都很好地解释了这些概念。

实用性胜过纯粹

这句格言与前一句相矛盾,它提醒我们保持它们之间的平衡

永远不要默默地忽视错误

放过错误最终会留下隐式 Bug,并且这些 Bug 更难被发现。Python 提供了健壮的错误处理,与其他语言相比,程序员使用该工具并不难。


try:    x = int(input("Please enter an Integer: "))except ValueError:    print("Oops! This is not an Integer.")   except Exception as err:    print(err)else:    print('You did it! Great job!')finally:    print('ヽ(✿゚▽゚)ノ') # 1.这段代码可能中断。# 2.如果出现值错误就会触发。# 3.处理值错误之外的错误。# 4.如果没有触发错误就执行。# 5.不管是否触发错误都执行。
复制代码


根据Python文档:“即使一个语句或表达式在语法上是正确的,在试图执行它时也可能会导致错误。”


特别是对于大型项目,我们不希望在耗时的计算后,代码崩溃。这就是异常管理的魅力所在。

除非明确需要这样做

在某些情况下,小错误不会困扰你。不过,也许你想捕获特定错误。要获得关于特定错误消息的更多细节,我建议阅读官方的内置异常文档并找到你需要的内容。

面对模棱两可,拒绝猜测

重要的是要不断学习,享受挑战,容忍歧义。我们都不知道最终会怎样。——玛蒂娜·霍纳


这句话优雅而抒情,但在编程中不是一个好的隐喻。歧义可能是指不清楚的语法、复杂的程序结构或触发错误消息的错误。例如,第一次使用numpy模块时的一个简单错误:


import numpy as np
a = np.arange(5)print(a < 3)if a < 3: print('smaller than 3')
复制代码


ValueError: 具有多个元素的数组的真值不明确,请使用 a.any()或 a.all()


如果执行上面代码,你将在输出中发现一个由 5 个布尔值组成的数组,表明值在 3 以下。因此,if语句不可能确定状态。消息中显示的内置函数.all()和.any()用于代替 And/Or。


import numpy as np
a = np.array([True, True, True])b = np.array([False, True, True])c = np.array([False, False, False])
print(a.all())print(a.any())
print(b.all())print(b.any())
print(c.all())print(c.any())
复制代码


输出表明,.all()仅在所有项都为True时才返回True,而.any()在有一项为True时就返回True

解决问题最直接的方法应该有一种,最好只有一种

想想为什么 Python 被描述为一种易于学习的编程语言。Python 具有非凡的内置函数/库和高度的可扩展性,它鼓励程序员优雅地编写代码。尽管有更多的解决方案可以提供灵活性,但对于同一个问题,它们可能会花费更多时间。



输入 import antigravity 并执行

当然这是没法一蹴而就的,除非你是荷兰人

Python 之父Guido van Rossum是一位荷兰程序员,他让这句格言变得无可争议。你不会声称自己比他更了解 Python……至少我不会。



照片来自 GitHub

做也许好过不做

你可以拖延,但时间不会,失去的时间一去不复返。——本杰明·富兰克林


对于那些像我一样患有拖延症,正在寻求改变的人,看看这个,和恐慌怪兽合作。


另一方面,这个格言的另一个方面是阻止你过度计划,这并不比看 Netflix 更有效率。


拖延和过度计划的共同特征就是“什么都做不了。”

不想就做还不如不做

“做也许好过不做”并不意味着计划没用。把你的想法写下来,设定一个要征服的目标,比不想就做要好。


例如,我通常在每个星期天花一个小时来制定我的周计划,并在睡觉前更新我明天的计划,看看有什么需要推迟的事情。

如果解决方案难以解释清楚,那一定很糟糕

回想一下“复杂胜于晦涩”的理念。通常,晦涩的代码意味着弱设计,特别是在像 Python 这样的高级编程语言中。


然而,在某些情况下,其领域知识的复杂性可能会让实现难以解释,而如何优化让其明晰易懂至关重要。这里有一个规划项目指南,可以给你提供帮助。

如果实现容易描述,那可能是个好方案

使设计(甚至人们的生活)更容易,即使背景知识可能很深刻,这是编程的专业知识,我认为也是编程中最困难的部分。


利用 Python 的简单性和可读性来实现一些疯狂的想法。

命名空间是一种绝妙的理念,多加利用!

最后但同样重要的是,命名空间是一组符号,用于组织各种对象,以便这些对象可以通过惟一的名称引用。在 Python 中,命名空间是由以下元素组成的系统:


  1. 内置命名空间:可以在不创建自定义函数或导入模块(如print()函数)的情况下调用。

  2. 全局命名空间:当用户创建一个类或函数时,将创建一个全局命名空间。

  3. 局部命名空间:局部作用域中的命名空间。



命名空间关系图


命名空间系统可以防止 Python 模块名称之间产生冲突。


英文原文:


How to Make Your Python Code More Elegant


2020-04-03 22:475368
用户头像

发布了 693 篇内容, 共 402.1 次阅读, 收获喜欢 1502 次。

关注

评论

发布
暂无评论
发现更多内容

Java模块化应用实践之精简JRE | 京东云技术团队

京东科技开发者

Java jre 企业号10月PK榜 Java21

3D模型如何添加金属贴图?

3D建模设计

材质 纹理 金属贴图

EVE-NG的环境导入IOL组件

小魏写代码

数字化转型如何落地?

优秀

数字化转型 数字化业务转型

可视化(Visual) SQL初探

数新网络官方账号

数据库 sql #数据库

逻辑漏洞挖掘之CSRF漏洞原理分析及实战演练 | 京东物流技术团队

京东科技开发者

CSRF 安全测试 漏洞分析 逻辑漏洞 企业号10月PK榜

App 支付报错“商家订单参数异常,请重新发起付款“排查流程

盐焗代码虾

支付宝 支付宝报错 排查思路 APP支付

多链多签名数字货币加密货币

西安链酷科技

区块链 软件开发 dapp 去中心化 钱包

面向Three.js开发者的3D自动纹理化开发包

3D建模设计

AI 3D模型 three.js AI自动纹理

写出一个复杂的SQL步骤

程序员万金游

#数据库 #java #Mysql #SQL

浅谈搜索展现层场景化技术-tanGo实践

百度Geek说

企业号10月PK榜 搜索场景化 展现层技术 阿拉丁

mybatis plus很好,但是我被它坑了!

越长大越悲伤

Java MySQL mybatis Mybatis Plus

涛思数据与胜软科技达成战略合作,共同赋能石油行业数字化转型

TDengine

tdengine 时序数据库

去中心化应用程序(DAPPS)开发

西安链酷科技

分布式 dapp 去中心化 交易所

企业内部外网向内网传输文件如何实现高效安全?

镭速

内外网数据交换 内部外网隔离

专业好用的多媒体播放器Infuse 最新版中文

胖墩儿不胖y

Mac软件 多媒体播放器

QCN9024 with IPQ4019|Wallys Dual Band Card DR9074E: Unleash the Power of Open Source Networking

wallyslilly

IPQ4019 QCN9074

用友BIP,IoT在光伏行业的应用

用友BIP

物联网 智能制造

全球业务 | 用友废钢智能判级系统在日本成功通过验收

用友BIP

废钢智能判级

代币开发工具:从 Truffle 到 Hardhat

区块链软件开发推广运营

交易所开发 dapp开发 区块链开发 链游开发 NFT开发

40 + 专家齐聚共谋数据未来,StarRocks Summit 2023 议程公布!更多精彩议题等你探索...

StarRocks

数据库 OLAP StarRocks

记一次老商家端应用内存突然飚高原因分析 | 京东物流技术团队

京东科技开发者

企业号10月PK榜 fullGC 内存飙升

如何选择安全又可靠的文件数据同步软件?

镭速

数据实时同步

赣州有资质等保测评机构有几家?咨询电话多少?

行云管家

等保 等级保护 等保测评 赣州

中移链浏览器简介

BSN研习社

浅析Redis大Key | 京东云技术团队

京东科技开发者

redis key redis 底层原理 企业号10月PK榜

后期云端制作:激发影视行业创新力的新时代

Finovy Cloud

影视制作 云渲染 后期制作

如何为模型添加光照效果?

3D建模设计

材质 纹理 光照贴图

苹果mac电脑矢量插画设计推荐 Illustrator 2024 补丁激活版中文

mac大玩家j

Mac软件 矢量设计 Mac软件矢量工具

Downie 4 for Mac(视频下载软件) 4.6.33和谐直装版

mac

视频下载工具 Downie4 苹果mac Windows软件

第18期 | GPTSecurity周报

云起无垠

怎样让你写的Python代码更优雅?_语言 & 开发_Hannibal Liang_InfoQ精选文章