python pythonic是什么?
原文地址:http://faassen.n--tree.net/blog/view/weblog/2005/08/06/0
注:Martijn 是 Zope 领域的专家,他为 Zope 系列产品做了许多开发工作,也开发了 lxml 等多个开源产品。你可以在这里了解一下他的信息http://www.zope.org/Members/faassen。这篇文章写于 2005 年,虽然有少部分内容(主要是例子)看起来已经有些过时,但即便是在今天,它的中心思想依然有极高的指导意义。
这是几个月前在 EuroPython 邮件列表(主要用来组织和计划 EuroPython 会议的邮件列表)出现的问题。这是一个非常有意思的问题,我看到这个词被无数次地使用,但鲜有人尝试解释它的含义。在这条线索之后,许多不同的人,包括我自己,都给出了自己的答案。现在我把我的答案放到博客上,并且润色了一下,希望它能对您有所增益。
Pythonnic 是一个模糊的概念,尽管没有“智能”或“生命”那么模糊,但当你尝试定义它们的时候,就像去抓住一条滑溜溜的泥鳅一样无从下手。可是虽然它们难以定义,然而并不意味着它们没用,因为事实上人们其实极善于利用混乱的定义。Pythonic 有点像“Python惯用法”的意味,现在让我们来聊聊它真正的含义。
随着时间的推移,Python语言不断演进,社区不断成长,涌现了许多关于如何正确地使用Python 的 ideas。一方面 Python 语言推荐使用大量的惯用法来完成任务(“完成任务的唯一方法”),另一方面,社区不断演变的新的惯用法的又反过来影响了语言的进化,以更好地支持惯用法。比如新进入的字典的 .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,它并不是 Python 语言推荐的惯用法。让我们来改进一下。典型的 Python 惯用法是用内置的 range() 函数生成所有的序列下标:
for i in range(mylist_length):
do_something(mylist[i])
其实这种实现也并不 Pythonic,接下来大家看看语言推荐的实现方式,真正 Pythonic 实现:
for element in mylist:
do_something(element)
“如何直接传递或改变引用”是comp.lang.python 的“月经贴”,但在只有赋值(import、class、def 等语句也可视为赋值)的 Python 中这是不可能的。这种需求通常是因为想让函数返回多个值,用 C 或者许多其它编程语言的方法是给这个函数传入引用或指针:
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]
显然这是毫无 Pythonic 可言的实现。Python 中让函数返回多个值的惯用法与此迥异,得益于元组和元组解包,它看起来也要漂亮得多:
def foo():
return 3, 5.5
alpha, beta = foo()
在经验老到的 Python 程序员看来,不够 Pythonic 的代码往往看起来古怪而且累赘,过于冗余也难以理解。因为它使用冗长的代码代替常见的、公认的、简短的惯用法来实现预期效果。更甚于此的是在语言支持正确的惯用法之后,非推荐的代码通常执行起来更慢。
Pythonic 就是以清晰、可读的惯用法应用Python 理念和数据结构。举个例子,应该多使用动态类型,在无必要之处引入静态类型就走向了另一端。另外也要避免使用经验丰富的 Python 程序员不熟悉的方式去完成任务(即遵循最小惊奇原则)。
Pythonic 一词也能够适用于底层的惯用法。一个 Pythonic 的库或框架能使程序员更加容易、更加自然地学会利用它来完成任务。如果用 Python 编写的库或框架迫使程序员编写累赘的或不推荐的代码,那么可以说它并不Pythonic。也许可能是为了使这个库更加方便、易懂,而没有应用Python 的一些理念,如类等,那也是不 Pythonic 的。类定义应当尽可能地实现信息隐藏,虽然Python 的许多操作都只作“宽松限制”(通常由程序员在属性的前面加上一个下划线来暗示这是私有成员),但也要做得像 Java 那样严格。
当然,当规模很大的时候,它是否 Pythonic 就极具争议性了。这里给出一些参考条款:如减少冗余,Python 的库与 APIs 都倾向于小型化和轻量化(相对于 java 程序库而言)。重量级的、API过于细化的的Python 库并不 Pythonic。比如 W3C XML DOM API,尽管它的 Python 实现已经颇有时日,但大家并不认为它 Pythonic。有些人认为它是 Java 式的,虽然也有许多 Java 程序员认为并不如此。
一个Pythonic的框架不会对已经用惯用法完成的东西重复发明轮子,而且它也遵循常用的Python 惯例。
当然,问题是构建框架时肯定会不可能避免地引入一些你不熟悉的模式和方法。Zope2 是我极为熟悉的一个框架,它也是一个引入了许多完成工作的特定的方法(如 Acquisition)的例子,这些方法往往什么地方都用不到,因此许多经验丰富的 Python 程序员认为它并不 Pythonic。
创建 Pythonic 的框架极其困难,什么理念更酷、更符合语言习惯对此毫无帮助,事实上这些年来优秀的 Python 代码的特性也在不断演化。比如现在认为像 generators、sets、unicode strings 和 datetime 之类的特性尤为 Pythonic。Zope2 的历史悠久,它从1997年开始开发,你不能把不够 Pythonic 归咎于它,甚至考虑到这么多年来它控制得如此之好,更应该感谢它。
关于 Pythonicness 的新趋势的一个例子是Python 的包和模块结构日益规范化。新的代码库如Twisted、Zope3 和 PyPy 等或多或少都跟随了这样的潮流:
- 包和模块的命名采用小写,单数形式,而且短小。
- 包通常仅仅作为命名空间,如只包含空的 __init__.py 文件。
在我写库(如 lxml)的时候也遵循了这样的惯例。
因为更多人认为一个 Python 程序员容易学习的功能不那么强大的框架比一个需要大量时间来学习的强大系统更为 pythonic。所以有时我认为宣称软件不够 Pythonic 不公平,甚至可能会因此而掩盖了该软件积极的一面。
最后,作为什么是 Pythonic 的扩充材料,可以尝试一下在 Python 解释器里执行如下语句:
import this
译者:赖勇浩(http://blog.csdn.net/lanphaday)
import this内容:
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.
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!
– by Tim Peters
翻译:
python pythonic是什么?的更多相关文章
- [python]pythonic的字典常用操作
注意:dct代表字典,key代表键值 1.判断字典中某个键是否存在 实现 dct.has_key(key) #False 更Pythonic方法 key in dct #False 2.获取字典中的值 ...
- python -- Pythonic
所谓Pythonic,就是极具Python特色的Python代码(明显区别于其它语言的写法的代码) 总结如下: 两变量的内容交换 Python:a,b = b,a 非Python:t=a;a=b;b= ...
- [python] Pythonic语法笔记
Pythonic语法笔记 __new__ 在类实例化之前执行的,也就是在init之前执行,可以为这个类写操作.接受的参数不是self而是cls.只有在new方法里返回类才会执行init操作,需要返回父 ...
- 让你的Python代码更加pythonic
http://wuzhiwei.net/be_pythonic/ 何为pythonic? pythonic如果翻译成中文的话就是很python.很+名词结构的用法在中国不少,比如:很娘,很国足,很CC ...
- 老齐python-基础3(列表)
1.定义一个列表 >>> a = [] #创建一个空列表 >>> type(a) #查看数据类型 <class 'list'> >>> ...
- 一些Python的惯用法和小技巧:Pythonic
Pythonic其实是个模糊的含义,没有确定的解释.网上也没有过多关于Pythonic的说明,我个人的理解是更加Python,更符合Python的行为习惯.本文主要是说明一些Python的惯用法和小技 ...
- 如何让你的Python代码更加pythonic ?
pythonic如果翻译成中文的话就是很python.很+名词结构的用法在中国不少. 以下为了简略,我们用P表示pythonic的写法,NP表示non-pythonic的写法,当然此P-NP非彼P-N ...
- Be Pythonic ,Google Python Style Guide
为了更规范的写代码,变得更专业 分号 1 不在句末添加分号,不用分号在一行写两句代码 行长度 2 每行不超过80字符,python会隐式行连接圆括号,中括号,花括号中的字符,如多参数方法调用可以写为多 ...
- [Python]更加Pythonic的多个List合并和Python的安利
原题: https://segmentfault.com/q/1010000005904259 问题: 倘若存在 L=[ [1,2,3],[4,5,6],[7,8,9]] 这样的列表,如何把合并成[1 ...
随机推荐
- 第七届河南省赛H.Rectangles(lis)
10396: H.Rectangles Time Limit: 2 Sec Memory Limit: 128 MB Submit: 229 Solved: 33 [Submit][Status] ...
- Good Luck in CET-4 Everybody!(博弈)
Good Luck in CET-4 Everybody! Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K ...
- ftp读取txt数据并插入数据库
去官网下载http://enterprisedt.com/ .netftp组件 目前最新版本为2.2.3,下载后在bin目录中找到edtFTPnet.dll,在项目中添加引用. using Enter ...
- Ubuntu 14.10 编译 qt4.8.6
0. 假设你已经可以在上面写基本的C++程序.(即:c/C++开发环境已经就绪)1. $ sudo apt-get build-dep libqt4-dev 2. $ sudo apt-get ins ...
- javascript函数querySelector
querySelector用于获得dom节点,可以接受三种类型的参数:id(#),class(.),标签.很像jquery的选择器.不过只能返回一个子孙元素,但是jquery选择器的话,可以返回一组元 ...
- django 实现指定文件合并成压缩文件下载
需求是在一列学生列表中选择指定的学生,然后下载他们上传的报告文档.
- Angulajs 定时器使用
在Angulajs的control中,不能利用 window.setInterval和 setTimeout 来操作定时器,因为这样做,虽然设置定时器会成功,但对$scope中的数据进行设置时,不会自 ...
- Oracle中sign函数和decode函数的使用
Oracle中sign函数和decode函数的使用 1.比较大小函数SIGN sign(x)或者Sign(x)叫做 符号函数,其功能是取某个数的符号(正或负): 当x>0,sign(x)=1; ...
- Android Manifest.xml 结构详解
关于AndroidManifest.xml AndroidManifest.xml 是每个android程序中必须的文件.它位于整个项目的根目录,描述了package中暴露的组件(activities ...
- http://qt-project.org/wiki/Category:Developing_with_Qt::QtWebKit#ff7c0fcd6a31e735a61c001f75426961
404: Not Found | Qt Project QtWebKit documentation http://dwz.cn/hr2013