关键字(Keyword):Python,Python之禅,The Zen of Python,程序,编程,import this
目录:
关于Python之禅(The Zen of Python)
Python之禅的逐行解释(包含代码例)
附录1:中译Python之禅全文
附录2:this.py的源码

学习一门编程语言时,首先要学习的是语言的设计思想和理念!
所谓"禅",是一种人类锻炼思维生发智慧的生活方式(出处:百度百科),能称之为禅的作品通常皆为大家之作,令人叹为观止。
另一方面,"禅"一般又都意味深长,仁者见仁智者见智,不同人有不同的理解。
01
—
关于Python之禅(The Zen of Python)
Python之禅(The Zen of Python),是Python元老蒂姆·彼得斯(Tim Peters)1999年编写并发布在Python邮件列表中的"Python设计指导原则",原名"The Way of Python" 。
通过理解Python之禅这套设计指导原则,则能够更深入理解Python的编程理念极其精髓,进而大大提高Python代码的质量和效率,因此值得每个Python学习者细细品读。
该原则一共20条,Tim完成了19条,而第20条留白给Python语言最初设计者及主要架构师Guido van Rossum 填写(至今留白)。
参考:Zen of Pythonhttps://en.wikipedia.org/wiki/Zen_of_PythonPEP 20 -- The Zen of Pythonhttps://www.python.org/dev/peps/pep-0020/
Tim的Python 之禅被列为Python官方改进提案的第20条,并且作为彩蛋包含在Python的编译器中(this.py),可以通过在Python的命令行中输入import this来显示全文。
例:
C:\Users\TeacherWhat>pythonPython 3.7.7 (tags/v3.7.7:d7c567b08f, Mar 10 2020, 10:41:24) [MSC v.1900 64 bit (AMD64)] on win32Type "help", "copyright", "credits" or "license" for more information.>>> import thisThe Zen of Python, by Tim PetersBeautiful is better than ugly.Explicit is better than implicit.Simple is better than complex.Complex is better than complicated.Flat is better than nested.Sparse is better than dense.Readability counts.Special cases aren't special enough to break the rules.Although practicality beats purity.Errors should never pass silently.Unless explicitly silenced.In the face of ambiguity, refuse the temptation to guess.There should be one-- and preferably only one --obvious way to do it.Although that way may not be obvious at first unless you're Dutch.Now is better than never.Although never is often better than *right* now.If the implementation is hard to explain, it's a bad idea.If the implementation is easy to explain, it may be a good idea.Namespaces are one honking great idea -- let's do more of those!
02
—
Python之禅的逐行解释(包含代码例)
下面是参考网文翻译以及理解整理的Python之禅逐行解释,供大家参考:
主要参考:プログラマが持つべき心構え (The Zen of Python)https://qiita.com/IshitaTakeshi/items/e4145921c8dbf7ba57efThe Zen of Python [Stack Overflow]https://web.archive.org/web/20140526061824/http://stackoverflow.com/questions/228181/the-zen-of-python
优美胜于丑陋
例1 :(参考回答:J.T. Hurley)
Python可以使用少量的代码(4行)计算最大公约数。
def gcd(x, y):
while y:
x, y = y, x % y
return x
数学上的优美来自于算法,当算法优美时,代码也会很优美。
Python可以用少量的行来表达出算法的优美。
例2 :(参考回答:dheerosaur )
逻辑运算符-分别使用and, or代替&&,||
尽管这个看法很主观的,但这种方式看起来更易读和美观。
if (is_valid(a) && b == 0 || s == 'yes') {
if is_valid(a) and b == 0 or s == 'yes':
显式优于隐式
例1:(参考回答:Federico A. Ramponi)
不要这样写代码
from os import *
print getcwd()
相反,当引用某函数时,应该让代码能够轻松查看从哪个模块提供了该功能。
import os
print os.getcwd()
另外请参考如下内容:
Namespaces are one honking great idea - let's do more of those!
命名空间是一种绝妙的理念,我们应当多加利用
因此,在Python中,当调用方法或引用字段时,即使在类中也要指定self。程序员应该始终知道他们正在使用什么对象以及它们在哪里。
例2:(参考回答:Xiong Chiamiov )
应用用于语言本身。
通常脚本语言允许这样的操作:
<?php
$foo = "5";
echo $foo * 3;
?>
执行结果:
[$]> php test.php
15
发生这种情况是因为在计算字符串x整数时,字符串被视为整数。这称为隐式类型转换。
但是在Python中执行相同操作的话,结果如下:
>>> foo = "5"
>>> foo * 3
'555'
即打印该字符串乘以整数次。
Python虽然是动态类型的(不需要事先声明变量),但它是强类型语言。强类型指一个变量被赋值为一个对象后,这个对象的类型就固定了,不能隐式转换成另一个类型。
如果执行如下操作,结果将产生异常。
>>> foo+3
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: cannot concatenate 'str' and 'int' objects
如果你确实想要这样做,那么需要明确地告诉Python,想要的结果一个整数。
>>> int(foo)+3
8
简洁胜于复杂
例1:(参考回答: ddaa )
比较一下C和Python的打印命令。
C语言
#include <stdio.h>
int main(void) {
printf("Hello, world!\n");
return(0);
}
Python语言:
print "Hello, world!"
即使使用相同的“ Hello,World!”,C和Python之间的实现非常不同。
使用Python,您可以一目了然地看到您的代码在做什么,更简洁。
※上面的回答原文是放在了可读性中,个人认为放在简洁性更恰当。
例2:
如同java,c#等高级语言一样,Python具有自动内存垃圾回收机制,一般不需要程序员来处理,从而让程序员更专注于业务实现。
参考:
深度解析Python垃圾回收机制(超级详细)
http://c.biancheng.net/view/5540.html
复杂胜于难懂
复杂(Complex)和难懂(complicated)看起来很相似,但是其含义并不相同。
因此,Python之禅说:只要有合理的需求,也可以构建非常复杂的应用程序。
例:(参考回答: EinLama)
counter = 0
while counter < 5:
print(counter)
counter += 1
这段代码应该很容易理解,并不复杂,但是却很难懂。
在一个代码中混杂了“计数器变量的管理(counter += 1)”和“通过打印语句显示值(print(counter))”两个元素。
事实上,你不需要手动执行上面的大多数步骤。
for i in xrange(5):
print i
这段代码比while示例更复杂,但是“计数器变量的管理(counter += 1)”和“通过打印语句显示值(print(counter))”这两个元素被明确分开。
也许那些不了解xrange的人可能不知道这段代码在做什么。但是,找出xrange用于编写干净的代码的代价并不高。通过阅读文档就可以立即了解接口xrange的行为。
所以,许多步骤隐藏将在简洁的接口中,更易于管理。
代码越多,难懂代码和复杂代码之间的可管理性差异就越大。
一般的经验法则是遵循Python Zen的其他原则:
If it is hard to explain, it is not a good idea.
如果很难解释,那肯定不是一个好方案
If it's easy to explain, it might be a good idea.
如果很容易解释,那也许是一个好方案
参考:
https://stackoverflow.com/questions/4568704/what-does-complex-is-better-than-complicated-mean
扁平胜于嵌套
例:(参考回答: S.Lott)
Python标准库中的模块种类非常多,能够满足各种需求。
而且和其他语言(如Java和C++)不同,一般没有复杂的类继承等深层嵌套;
Python会将一堆类定义和单例对象创建堆积到单个模块文件中。
因为Python的命名空间是扁平的,因此使用标准模块时无需使用长名com.company.java.blah.blah,通常仅需要简单地import即可(例如:import os),
很多库都遵循这个“扁平比嵌套更好” “风格。
间隔胜于紧凑(不要试图在一行上粘贴太多代码)
例:(参考回答: ddaa)
没有间隔的代码:
if i>0: return sqrt(i)
elif i==0: return 0
else: return 1j * sqrt(-i)
有适当的间隔的代码:
if i > 0:
return sqrt(i)
elif i == 0:
return 0
else:
return 1j * sqrt(-i)
上面的代码或下面的代码哪个更易于阅读?
用另一种方式改写这个原则“不要试图在一行上粘贴太多代码”。
可读性很重要
这些原则中的许多似乎在逻辑上是重叠的。
例1:
Python语言本身而言,做到最少标点符号。
例如通过分号:表示条件的后续执行或函数的内部内容。
各行代码之后无需任何符号等。
x,y=10,100
if(x < y):
st ="X 比 Y 小"
elif(x == y):
st ="X 等于Y"
else:
st ="X 比 Y 大"
print (st)
例2:
编写程序时考虑添加适当的注释,块结构的空白(考虑缩进、空格)等帮助阅读代码
特殊情况不足以打破规则
例:(参考回答: Federico A. Ramponi)
长度为1的字符串不够特殊,不值得使用专用的char类型。
a = 'c'
print(type(a))
结果:
class 'str'
参考:
Does python support character type?
https://stackoverflow.com/questions/47310929/does-python-support-character-type
然而,实用性大于纯粹性。
这条原则是关于原则8的补充,原则8也可能有例外。
例:(参考回答: Federico A. Ramponi)
这就是为什么我们拥有chr()和ord())两个内置函数的原因。
参考:
浅谈Python内置函数chr、ord
https://www.jianshu.com/p/3e29bda3b42c
python ord()与chr()用法以及区别
https://www.cnblogs.com/sui776265233/p/9103251.html
不要隐藏错误,不要忽略错误。
尝试捕获异常。
例:(参考回答:Ali Afshar)
例如不要写如下的except...pass的代码
try:
import this
except ImportError:
pass
应该显式地捕获异常。
try:
import this
except ImportError:
print('this is not available')
除非是故意忽略错误
第10条和11条原则大意可以理解为为:除非需要(经过深思熟虑的结果),否者应该捕获所有的错误。
例1:(参考回答:Ali Afshar)
看看下面一段代码
d = dict((('spam', 1), ('ham', 2)))
default = 0
k = 'eggs'
try:
v = d[k]
except KeyError:
v = d[k] = default
print("v:{}".format(v))
print("d:{}".format(d))
执行结果如下:
$python silenced.py
v:0
d:{'eggs': 0, 'ham': 2, 'spam': 1}
这段代码表示如果d[k] 不存在,将密钥设置为默认值。
except子句不会通知外部发生了错误。因为是故意这样做的。
例2:Python中关于错误的处理
--2.1 异常和回溯(Exceptions and Tracebacks)
def f(n):
if n > 0:
return n * f(n-1)
return 1
print f('5')
执行结果
PS C:\Users\TeacherWhat> & python "c:/Users/TeacherWhat/Desktop/hello.py"
File "c:/Users/TeacherWhat/Desktop/hello.py", line 52
print f('5')
SyntaxError: invalid syntax
File "c:/Users/TeacherWhat/Desktop/hello.py", line 61
print f('5')
^
SyntaxError: invalid syntax
--2.2 引发异常(Raising Exceptions)
def f(n):
if not isinstance(n, int):
raise TypeError('n should be an int')
if n > 0:
return n * f(n-1)
return 1
print (f('5'))
执行结果
PS C:\Users\TeacherWhat> & python "c:/Users/TeacherWhat/Desktop/hello.py"
Traceback (most recent call last):
File "c:/Users/TeacherWhat/Desktop/hello.py", line 61, in <module>
print (f('5'))
File "c:/Users/TeacherWhat/Desktop/hello.py", line 56, in f
raise TypeError('n should be an int')
TypeError: n should be an int
--2.3 捕获异常(Catching Exceptions)
def f(n):
if not isinstance(n, int):
raise TypeError('n should be an int')
if n > 0:
return n * f(n-1)
return 1
try:
print(f('5'))
except TypeError as err:
print('Had an error:', err)
else:
print('No error')
finally:
print('Always run')
执行结果
PS C:\Users\TeacherWhat> & python "c:/Users/TeacherWhat/Desktop/hello.py"
Had an error: n should be an int
Always run
参考:
An Introduction to the Zen of Python
Doug Hellmann February, 2011
面对不明确的语义时,拒绝猜测。
例1:(参考回答:J.F. Sebastian )
该条件什么时候成立?
if not a and b:
pass
像如下重写?
if b and not a:
pass
或者虽然有点笨拙,最好写成如下。
if (not a) and b:
pass
例2:
print (5 * 1.0)
print (2 ** 100)
print (2 * 'abc')
print (2 + 'abc')
执行结果
PS C:\Users\TeacherWhat> & python "c:/Users/TeacherWhat/Desktop/hello.py"
5.0
1267650600228229401496703205376
abcabc
Traceback (most recent call last):
File "c:/Users/TeacherWhat/Desktop/hello.py", line 88, in <module>
print (2 + 'abc')
TypeError: unsupported operand type(s) for +: 'int' and 'str'
应该找一种(最好唯一)显而易见的解决方案。
与Perl编程语言的座右铭“There’s more than one way to do it!(有不止一种方法!)”不同,Python旨在消除冗余,通过一种最佳方法解决问题。
事实证明,用三种或四种不同的方式来编写可完成相同任务的代码是一把双刃剑:编写代码具有灵活性,但是必须学习各种可能的编写方式才能阅读它;这种灵活性不值得学习编程语言所需的3倍或4倍的努力。
这也是为什么Python的标准库删除重复的模块的原因,每种需求都应该有一个模块。
然而,最初这(第13条)也许并不容易,毕竟我们都不是Python之父。
找到一种显而易见的解决方案,在一开始并不容易,毕竟我们都不是Python之父。
这里的“Dutch”(荷兰人)指Guido van Rossum( Python的创建者,荷兰人)
参考:
Is the 14th line of The Zen of Python a reference to Dijkstra?
https://softwareengineering.stackexchange.com/questions/148790/is-the-14th-line-of-the-zen-of-python-a-reference-to-dijkstra
例1:(参考回答:S.Lott )
关于条件语句if-then-else(C语言中的cond?expr1:expr2)引起了激烈的争论。Guido在其中建议了如下这一点。
a = expr1 if cond else expr2
这是在Python中编写if-then-else条件语句的唯一方法。但是,乍一看很难理解,也许是文化或知识的差异。
a = 10
b = 20
print('a的值比较大!') if a > b else print('b的值比较大!')
执行结果:
b的值比较大!
参考:
Python三目运算符(三元运算符)用法详解
http://c.biancheng.net/view/2187.html
python条件(三元)运算符
https://www.cnblogs.com/FlyingLiao/p/11111871.html
做好过不做
例1:(参考回答:wim )
never
f = open('stay_open.txt', 'w')
print ("文件名为: ", f.name)
f.write('这是个测试')
raise AssertionError('抛出异常')
f.close()
执行结果:
PS C:\Users\TeacherWhat> & python "c:/Users/TeacherWhat/Desktop/hello.py"
文件名为: stay_open.txt
Traceback (most recent call last):
File "c:/Users/TeacherWhat/Desktop/hello.py", line 129, in <module>
raise AssertionError('抛出异常')
AssertionError: 抛出异常
PS C:\Users\TeacherWhat> cat stay_open.txt
这是个测试
now
with open('will_be_closed.txt', 'w') as f:
print ("文件名为: ", f.name)
f.write('这是个文件测试')
raise AssertionError('抛出异常')
执行结果:
PS C:\Users\TeacherWhat> & python "c:/Users/TeacherWhat/Desktop/hello.py"
文件名为: will_be_closed.txt
Traceback (most recent call last):
File "c:/Users/TeacherWhat/Desktop/hello.py", line 136, in <module>
raise AssertionError('抛出异常')
AssertionError: 抛出异常
never的示例中,异常使其退出代码块,后续没有执行,文件没有正常关闭。「因为稍后再关闭」的想法会产生错误的代码。
now示例中,with语句会自动调用close()方法关闭文件,从而避免由于未关闭文件导致的磁盘数据丢失和内存泄漏。
当然也可以使用try:模块来解决第一种情况。
try:
f = open('will_be_closed.txt', 'w')
print ("文件名为: ", f.name)
f.write('这是个文件测试')
assert not '抛出异常'
finally:
f.close()
但是,请记住第一条原则:
1.Beautiful is better than ugly.
优美胜于丑陋
参考:
Does a File Object Automatically Close when its Reference Count Hits Zero?
https://stackoverflow.com/questions/1834556/does-a-file-object-automatically-close-when-its-reference-count-hits-zero/1834757#1834757
然而,有时不假思索就动手还不如不做(动手之前要细思量)
例:
过早地优化代码通常很耗时。
例如,要实现排序时,不需要从头开始就实施快速排序。
因为通常快速排序比气泡排序更难实现,所以如果气泡排序就足以解决问题,没必要从一开始就进行快速排序将浪费时间。
在测试阶段,暂时使用冒泡排序,并在必要时将其重写为快速排序。
如果你无法浅显易懂地解释你的代码,那肯定不是一个好方案
如果你能浅显易懂地解释你的代码,那也许是一个好方案
命名空间是一种绝妙的理念,我们应当积极使用
例1:(参考回答:Johan )
导入模块时应该如下:
# import everything from a module
import module
# call some function in the module
module.spam()
# import some class from module
import module
breakfast = module.SpamAndEggs()
最好不要这样写:
from module import *
除了为了方便在命令提示符下进行测试外,您不应该如此编写代码。
因为如果在常规程序中这样编写的话,可能会发生模块名称冲突。另外,由于不知道该功能属于哪个模块,会降低了可读性。
如果模块名称或类名称很长,可以使用as。
# long module name
import aRidiculouslyLongModuleName as short
# long class name
from aRidiculouslyLongModuleName import RatherLongClassName as ShortClass
其他参考:
import module与from module import * 两种模块导入有何区别
https://www.cnblogs.com/chichung/p/9610500.html
Python入门基础之导入问题:from import 与import 详解
https://baijiahao.baidu.com/s?id=1595360515695157210
03
—
附录1:中译Python之禅全文
综上所述,中译Python之禅全文如下,供参考:
The Zen of Python, by Tim Peters
## Python之禅 , by Tim Peters
Beautiful is better than ugly.
## 优美胜于丑陋
Explicit is better than implicit.
## 显式优于隐式
Simple is better than complex.
## 简洁胜于复杂
Complex is better than complicated.
## 复杂胜于难懂
Flat is better than nested.
## 扁平胜于嵌套
Sparse is better than dense.
## 间隔胜于紧凑(不要试图在一行上粘贴太多代码)
Readability counts.
## 可读性很重要
Special cases aren't special enough to break the rules.
## 特殊情况不足以打破规则
Although practicality beats purity.
## 然而,实用性大于纯粹性。
Errors should never pass silently.
## 不要隐藏错误,不要忽略错误
Unless explicitly silenced.
## 除非是故意忽略错误
In the face of ambiguity, refuse the temptation to guess.
## 面对不明确的语义时,拒绝猜测
There should be one-- and preferably only one --obvious way to do it.
## 应该找一种(最好唯一)显而易见的解决方案。
Although that way may not be obvious at first unless you're Dutch.
## 然而,最初这(第13条)也许并不容易,毕竟我们都不是Python之父。
Now is better than never.
## 做好过不做
Although never is often better than *right* now.
## 然而,有时不假思索就动手还不如不做(动手之前要细思量)
If the implementation is hard to explain, it's a bad idea.
## 如果你无法浅显易懂地解释你的代码,那肯定不是一个好方案
If the implementation is easy to explain, it may be a good idea.
## 如果你能浅显易懂地向人描述你的方案,那也许是一个好方案
Namespaces are one honking great idea -- let's do more of those!
## 命名空间是一种绝妙的理念,我们应当多加利用
04
—
附录2:this.py的源码
输出Python之禅这套设计指导原则的源码如下:
s = """Gur Mra bs Clguba, ol Gvz Crgref
Ornhgvshy vf orggre guna htyl.
Rkcyvpvg vf orggre guna vzcyvpvg.
Fvzcyr vf orggre guna pbzcyrk.
Pbzcyrk vf orggre guna pbzcyvpngrq.
Syng vf orggre guna arfgrq.
Fcnefr vf orggre guna qrafr.
Ernqnovyvgl pbhagf.
Fcrpvny pnfrf nera'g fcrpvny rabhtu gb oernx gur ehyrf.
Nygubhtu cenpgvpnyvgl orngf chevgl.
Reebef fubhyq arire cnff fvyragyl.
Hayrff rkcyvpvgyl fvyraprq.
Va gur snpr bs nzovthvgl, ershfr gur grzcgngvba gb thrff.
Gurer fubhyq or bar-- naq cersrenoyl bayl bar --boivbhf jnl gb qb vg.
Nygubhtu gung jnl znl abg or boivbhf ng svefg hayrff lbh'er Qhgpu.
Abj vf orggre guna arire.
Nygubhtu arire vf bsgra orggre guna *evtug* abj.
Vs gur vzcyrzragngvba vf uneq gb rkcynva, vg'f n onq vqrn.
Vs gur vzcyrzragngvba vf rnfl gb rkcynva, vg znl or n tbbq vqrn.
Anzrfcnprf ner bar ubaxvat terng vqrn -- yrg'f qb zber bs gubfr!"""
d = {}
for c in (65, 97):
for i in range(26):
作者使用了简单的ROT13加密算法,即将A→Z,a→z中每个字母往后移13位,然后输出。
参考:
The Zen of Python——this.py文件的解析
https://blog.csdn.net/mrbone11/article/details/53106432
05
—
其他
PEP 0 -- Index of Python Enhancement Proposals (PEPs) Python改进提案https://www.python.org/dev/peps/Tim Peters (software engineer)https://en.wikipedia.org/wiki/Tim_Peters_(software_engineer)https://mail.python.org/pipermail/python-list/1999-June/001951.htmlThe Python WayA Brief Analysis of “The Zen of Python”https://medium.com/@Pythonidaer/a-brief-analysis-of-the-zen-of-python-2bfd3b76edbfAn Introduction to the Zen of Pythonwww.slideshare.net/doughellmann/an-introduction-to-the-zen-of-pythonプログラマが持つべき心構え (The Zen of Python)https://qiita.com/IshitaTakeshi/items/e4145921c8dbf7ba57ef
相关阅读:
2019年Gartner新兴技术成熟曲线:物联网,数据科学与机器学习,人工智能和区块链
专注于技术不限于技术!
用碎片化的时间,一点一滴地提高数据库技术和个人能力。
欢迎关注!
关于小编:
10+年数据库运维/开发/技术支持经验,多年项目维护/开发/团队管理经验,熟悉Oracle/MySQL/DB2等关系型数据库,翻译出版《MySQL基础教程》,Oracle 11g OCM大师认证、10g/11g/12c OCP、RAC&GI OCE、Cloud等认证专家,IBM DB2 数据库V8.1 DBA认证。
本文仅代表个人观点,与任何公司无关。
原文作者:SQL和数据库技术;如有侵权,请联系管理员删除。