>>> from env_helper import info; info()
页面更新时间: 2023-12-27 09:18:58
运行环境:
Linux发行版本: Debian GNU/Linux 12 (bookworm)
操作系统内核: Linux-6.1.0-16-amd64-x86_64-with-glibc2.36
Python版本: 3.11.2
1.1. 理解Pythonic概念¶
什么是Pythonic?这是很难定义的,这就是为什么大家无法通过搜索引擎找到准确答 案的原因。但很难定义的概念绝非意味着其定义没有价值,尤其不能否定它对编写优美的 Python代码的指导作用。 对于Pythmiic的概念,众人各有自己的看法,但大家心目之中都认同一个更具体的指 南,那就是Tim Peters的《The Zen of Python》(Python之禅)。在这一充满着禅意的诗篇中,有几点非常深入人心:
美胜丑,显胜隐,简胜杂,杂胜乱,平胜陡,疏胜密。
找到简单问题的一个方法,最好是唯一的方法(正确的解决之道)。
难以解释的实现,源自不好的主意;如有非常棒的主意,它的实现肯定易于解释。
不仅这几点,其实《Python之禅》中的每一句都可作为编程的信条。 是的,不仅是作为 编写Python代码的信条,以它为信条编写出的其他语言的代码也会非常漂亮。
1.1.1. Pythonic 的定义¶
遵循Pythonic的代码,看起来就像是伪代码。其实,所有的伪代码都可以轻易地转换为 可执行的Python代码。比如在Wikipecha的快速排序e条目中有如下伪代码:
- function quicksort('array')
- if length('array') <= 1
return 'array' //an array of zero or one elements is already sorted select and remove a pivot element 1 pivot1 from 'array'
see 'Choice of pivot1 below create empty lists 'less 1 and *greater 1 ''' for each 'x1 in rarray'
if 'x' <='pivot' then append 'x' to 'less' else append 'x' to 'greater'
- return concatenate(quicksort <('less'), list('pivot'), quicksort('greater'))
//two recursive calls
实际上,它可以转化为以下同等行数的可以执行的Python代码:
>>> def quicksort(array):
>>> less=[];
>>> greater =[]
>>> if len(array) <=1:
>>> return array
>>> pivot = array.pop()
>>> for x in array:
>>> if x <= pivot: less.append(x)
>>> else: greater.append(x)
>>> return quicksort (less) + [pivot]+quicksort(greater)
看,行数一样的Python代码甚至可读性比伪代码还要好吧?但它真的可以运行,结果如下:
>>> quicksort ([9, 8,4, 5,32,64,2,1,0, 10, 19,27])
[0, 1, 2, 4, 5, 8, 9, 10, 19, 27, 32, 64]
所以,综合这个例子来说,Pythonic也许可以定义为:充分体现Python自身特色的代码风格。 接下来就看看这样的代码风格在实际中是如何体现的。
1.1.2. 代码风格¶
对于风格,光说是没有用的,最好是通过例子来看看,因为例子看得见,会显得更真实。 下面以语法、库和应用程序为例给大家介绍。 在语法上,代码风格要充分表现Python自身特色。 举个最常见的例子,在其他的语言 (如C语言)中,两个变量交换需要如下的代码:
int a = 1, b = 2; int tmp - a; a-b; b =tmp;
利用Python的 packaging/unpackaging 机制,Pythonic的代码只需要以下一行:
>>> a=1
>>> b=2
>>> a,b = b,a
还有,在遍历一个容器的时候,类似其他编程语言的代码如下:
>>> def do_sth_with(n):
>>> print(n)
>>>
>>> alist=[1,2,43,5,4]
>>> length = len(alist)
>>> i =0
>>> while i < length:
>>> do_sth_with(alist[i])
>>> i+=1
1
2
43
5
4
而Pythonic的代码如下:
>>> for i in alist:
>>> do_sth_with(i)
1
2
43
5
4
灵活地使用迭代器是一种Python风格。
又比如,需要安全地关闭文件描述符,可以使用以下 with
语句:
>>> with open('test_1.txt','r') as f:
>>> do_sth_with(f)
<_io.TextIOWrapper name='test_1.txt' mode='r' encoding='UTF-8'>
通过上述代码的对比,能让大家清晰地认识到Pythonic的一个要求, 就是对Python语 法本身的充分发挥,写出来的代码带着Python味儿而不是看着像C语言代码,或者Java 代码。
应当追求的是充分利用Python语法,但不应当过分地使用奇技淫巧,比如利用Python 的 Slice 语法可以写出如下代码:
>>> a = [1,2,3,4]
>>> c = 'abodef'
>>> print (a[::-1] )
>>> print (c[::-1])
[4, 3, 2, 1]
fedoba
如果不是同样追求每一个语法细节的”老鸟”,这段代码的作用恐怕不能一眼就看出来。
实际上,这个时候更好地体现Pythonic的代码是充分利用Python库里
reversed()
函数 的代码。
>>> print (list(reversed(a)))
>>> print (list(reversed(c)))
[4, 3, 2, 1]
['f', 'e', 'd', 'o', 'b', 'a']
1.1.3. 标准库¶
写Pythonic程序需要对标准库有充分的理解,特别是内置函数和内置数据类型。比如,对于字符串格式化,一般这样写:
>>> print ('Hello %s!' % ('Tom',))
Hello Tom!
其实是非常影响可读性的,因为数量多了以后,很难清楚哪一个占位符对应哪一个 实参。所以相对应的Pythonic代码是这样的:
>>> print('Hello %(name)s!' % {'name':'Tom'})
Hello Tom!
这样在参数比较多的情况下尤其有用。
>>> #字符串
>>> value = {'greet':'Hello world', 'language':'Python'}
>>> print ('%(greet)s from %(language)s.' % value)
Hello world from Python.
>>> print(
>>> '{greet} from {language}.'.format(
>>> greet = 'Hello world',
>>> language =' Python')
>>> )
Hello world from Python.
str.format()
方法非常清晰地表明了这条语句的意图,
而且模板的使用也减少了许多不必要的字符,使可读性得到了很大的提升。
事实上,str.format()
也成了
Python最为推荐的字符串格式化方法,当然也是最Pythonic的。
1.1.4. Pythonic的库或框架¶
编写应用程序的时候的要求会更高一些。因为编写应用程序一般需要团队合作, 那么可 能你编写的那一部分正好是团队的另一成员需要调用的接口,换言之,你可能正在编写库或 框架。 程序员利用Pythonic的库或框架能更加容易、更加自然地完成任务。 如果用Python编 写的库或框架迫使程序员编写累赘的或不推荐的代码, 那么可以说它并不Pythonic。 现在业内通常认为Flask这个框架是比较Pythonic的,它的一个Hello world级别的用例如下:
>>> # from flask import Flask
>>> # app = Flask( __name__ )
>>> # @app.route('/')
>>> def hello():
>>> return "Hello world!"
>>>
>>> if __name__ == '__main__':
>>> # app.run()
>>>
>>> print(hello())
Hello world!
稍有编程经验的人都可以通过上例认识到利用Python编程极为容易这一事实。 一个 Pythonic的框架不会对已经通过惯用法完成的东西重复发明“轮子”,而且它也遵循常用的 Python惯例。 创建Pythonic的框架极其困难,什么理念更酷、更符合语言习惯对此毫无帮助,事实上这些年来优秀的Python代码的特性也在不断演化。 比如现在认为像 generators 之类的特性尤为Pythonic。 另一个有关新趋势的例子是:Python的包和模块结构日益规范化。 现在的库或框架跟随了以下潮流:
包和模块的命名釆用小写、单数形式,而且短小。
包通常仅作为命名空间,如只包含空的
_init_.py
文件。