Advertisement

什么叫做pythonic_Pythonic到底是什么玩意儿?

阅读量:

Pythonic到底是什么'古怪'之处?

作者:Martijn Faassen

注:Martijn·J.是Zope领域的一位权威人士,在其职业生涯中为Zope系列产品提供了核心开发支持,并独立推出了lxml等多个开源项目。如需进一步了解相关信息,请访问其官方网站或相关资源页面。

就在最近,在专门用于组织和计划EuroPython会议的邮件列表中出现了一个有趣的问题。这个问题确实很有意思,在深入探讨这条线索后发现:尽管这个词已经被广泛使用过许多次甚至更多次但它鲜有对此进行过深入探讨的人对此进行了系统性的分析并总结出多种可能的用法以及相关的背景信息。经过这一系列的研究工作我们团队成员包括笔者自己都发表了自己的观点其中最值得一提的是笔者在这方面进行了较为深入的研究并在此基础上形成了自己的独特见解。
现将我的研究成果整理并优化后发布于博客平台相信会对您有所帮助。

Pythonic作为一个模糊概念存在,在某些情况下可能不如'智能'或'生命'那样具有高度抽象性。然而,在试图界定这些概念时却如同捉一只游得飞快的鱼一般令人困惑无措。尽管如此,在实践中即便如此也未必失去了其价值与意义;实际上人们往往能够巧妙地运用这些模糊概念解决问题。Pythonic的精神则类似于'Python惯用法'所体现的那种工作方式,在此我们便聚焦于探讨其真正内涵与应用价值吧!

随着时间的发展, Python语言持续发展, 社区持续壮大, 提出了许多创新性的使用Python的方法。一方面, Python语言鼓励开发者遵循大量成熟的编程范式(即所谓的"唯一方法")来完成各种功能;另一方面, 社区不断演变的新编程范式则反过来推动了语言自身的进化, 进一步完善现有的功能以适应性提升。例如, 在字典中新增introduced in Python 3.7的方法get(), 这一改进将has_key()以及元素存取两个操作整合为一个高效的操作, 这一演变充分展现了技术发展的趋势。

惯用法往往无法直接移植至其他编程语言。例如,在下文中可以看到如何在C语言中对序列中的每一个元素依次进行处理:

for (i=0; i < mylist_length; i++) {

do_something(mylist[i]);

}

直接的等效Python代码是这样的:

i = 0

while i < mylist_length:

do_something(mylist[i])

i += 1

这段代码能够执行其预期功能,并不具备Pythonic风格。它并非推荐使用的常见方法。我们可以对其进行优化以提高可读性与效率。常见的做法是利用内置函数range()来生成所需的索引序列:

for i in range(mylist_length):

do_something(mylist[i])

然而这种方法并非完全符合Python风格。让我们一起参考语言推荐的具体实施方案吧!真正的Pythonic实践:通过这种方式能够体现出代码设计的优雅与简洁。

for element in mylist:

do_something(element)

如何直接传递或转换引用对象

void foo(int* a, float* b) {

*a = 3;

*b = 5.5;

}

...

int alpha;

int beta;

foo(&alpha, &beta);

在Python中有一种相当麻烦的方法可以用来实现:函数被传递以返回结果的方式接受序列参数。写出来的代码可能像这样:

def foo(a, b):

a[0] = 3

b[0] = 5.5

alpha = [0]

beta = [0]

foo(alpha, beta)

alpha = alpha[0]

beta = beta[0]

很明显这种方法完全不符合Python风格。在Python中让函数返回多个值的传统方式与上述方法截然不同,在这种情况下我们主要依赖于元组以及通过解包元组来实现这一目标。

def foo():

return 3, 5.5

alpha, beta = foo()

资深Python程序员普遍认为不够Pythonic的代码往往显得怪异且冗长,并且过于繁琐难以理解。这是因为它们倾向于采用比标准简便方法更为复杂的方式实现同样的功能。值得注意的是,在遵循标准简便方法后,不推荐使用的代码通常运行速度较慢

可以说Pythonic是通过直观易懂的方式应用其核心理念和数据结构。比如,在没有必要设定具体类型的地方过度使用静态类型反而会偏离正确的方法。不要模仿那些资深开发者采用的方法,并且始终遵循最小惊奇原则来完成任务。

该术语也可应用于底层的习惯用法。
若依此类推设计,则会使得学习变得更加容易和自然。
若依此类推设计会导致程序员编写冗长且不推荐的操作。
或许是为了使其更容易理解和使用而不遵循类的相关原则。
类定义应尽可能实现信息隐藏。

然而,在面对大规模的数据或复杂场景时这一问题往往引发激烈的讨论

一个 Pythonic 的框架不需要对已有常用功能进行二次开发也不需要再创造它因为这些都已经在 Python 标准库中存在

当然,在构建框架的过程中,不可避免地会引入一些你不太熟悉的功能模块。对于我来说,Zope2是一个非常熟悉的框架;它不仅是一个使用方便的工具(如Acquisition),还提供了很多用于完成特定任务的独特功能。这些功能模块通常在各种场景中都不会派上用场。

创建Pythonic框架的过程异常复杂,并非任何一种理念能够显著提升代码的Pythonicity。随着时间的推移,优秀的Python代码逐渐演变为更加丰富的特征。例如,在当今开发者眼中,generators, sets, unicode strings以及datetime等特性往往被视为最具有Pythonic风格。
值得注意的是,Zope 2自1997年便开始开发,其对代码质量的卓越掌控能力并非偶然,反而应当受到高度赞扬。

一个关于Pythonicness新兴趋势的例证是Python的包和模块结构日益规范化。一些新的代码库如Twisted、Zope3和PyPy等在一定程度上遵循了这一潮流。

包和模块的命名采用小写,单数形式,而且短小。

包通常仅仅作为命名空间,如只包含空的__init__.py文件。

在我写库(如lxml)的时候也遵循了这样的惯例。

由于普遍认为对于一位熟练掌握Python编程语言的人来说,默认选择一个相对简单易学但功能较少的框架相比那些需要耗费大量时间去掌握而功能又强大的系统而言更为pythonic

最后一步就什么是Pythonic的扩充材料而言,在Python解释器中不妨试着执行以下代码:

import this

分享到:

18e900b8666ce6f233d25ec02f95ee59.png
72dd548719f0ace4d5f9bca64e1d7715.png

2008-08-03 21:17

浏览 549

评论

全部评论 (0)

还没有任何评论哟~