Code Like a Pythonista: Idiomatic Python


如果你有C++基础,那学习另一门语言会相对容易。因为C++即面向过程,又面向对象。它很底层,能像C一样访问机器;它也很高级,有模板、STL
等。如果认真读过《深入C++对象模型》,我想其它语言不会比这个更复杂。你对C++了解的越深,你用其它语言写出的代码就越像C++,这样就体现不出新
语言的价值了。所以,学习新语言要抛弃原有的潜意识,包括代码风格。

1. The Zen of Python (1)

漂亮比丑陋好
         清晰比隐含好
         简单比复杂好
         复杂比晦涩好
         平摊比嵌套好
         松耦合比紧耦合好
         可读性是有价值的
         特殊的条件不足以打破这些条款
         尽管实践打败理论的纯洁
         错误永远不要掩盖
         除非明确地平息它
         ……

2. PEP 8: Style Guide for Python

关于Python的重要风格准则

Whitespace1

  • 每级对齐为4个空格
  • 没有硬tab
  • 永远不要把tab与空格混用
  • 函数之间留出1行空白
  • 类之间留出2行空白

Whitespace 2

  • 在字典,列表,元组,参数列表的”,”后面加上空格,字典中”:”后也加上空格
  • 在赋值或比较符间加上空格
  • 在括号中要紧挨空格,函数名与括号也不要有空格
  • 在docstrings中不要立即空格

Naming

  • joined_lower用于函数,方法,属性
  • joined_lower或ALL_CAPS用于常量
  • StudlyCaps用于类, 不需要前面加C
  • #每字母大写
  • camelCase仅用于兼容已存在的惯例
  • 属性有:interface,_internal, __private。但后一种绝对不要使用。

一些来自C++/Java对类的访问权限过于在意。在Python中,MyClass.__private会直接解析为
MyClass._MyClass__private,因为它可以造成“视觉上”的不可访问。Python有条原则是:“we’reall
consenting adults
here”,你没有理由向我隐藏什么。子类有权力从父类继承属性,而父类有义务向子类提供相关文档来帮助其重写,而非拒绝。

Python倡导使用_internal来表示私有属性,它没有命令空间限制,而仅仅是善意提醒“be careful with this,
it's an internalimplementation detail; don't touch it if you don't fully understand it”

Long Lines &Continuations

在括号里的换行使用隐含换行,但要注意对齐

def __init__(self, first, second, third,
fourth, fifth, sixth):
output = (first + second + third
+ fourth + fifth + sixth)

其它换行要使用“\”,注意后面千万不要有空格

LongStrings

与C语言一样,两个相邻的字符串是可以被编译器自动连接的。有一点不同的是,C语言中字符串只有一种形式,即用””,但Python中可以有’’,””,r’’,’’’,”””等等。不过原理都是一样的。

组合语句

Python中不提倡将多条语句写在同一行。比如if语句等。Python是非常讲究通过缩进来显示代码的结构与流程。

交换值

Python中的元组是非常有意思且不被C语言系的人所察觉。

b, a = a, b

元组有非常好的通用性,列表与元组可以很容易地交换

a = [12, 34, 45]
b, c, d = a

元组还常常用在for语句中,用于一次处理多个索引

>>> people = [l, ['Guido', 'BDFL', 'unlisted']]
>>> for (name, title, phone) in people:
...     print name, phone

More About Tuples

Tuples的构造最重要的是“,”.比如、

>>> 1,
(1,)

即使上面没有括号也无妨。

Interactive “_”

在解释器中,_用于表示上次运算的结果。这种机制往往会给使用都很大的方便!

Building String from Substrings、、

这一条在Python世界中应该是很普及了。’’.join()只有在替代for循环连接列表时才有用

colors = ['red', 'blue', 'green', 'yellow']
result = ''
for s in colors:
    result += s

result = ''.join(colors) #这一条要比上面for循环更有效率

Used in where possible

首先,in是操作符而不是关键字;其次,所有的内建窗口都支持此操作符。作者要强调的是,in有两个常用的位置:1. 配合for执行遍历;2. 与if一起使用判断存在。

作者一再强调,字典重载的in操作是对象是所有的keys,所以没必要先调用d.keys()获取键的列表,再使用in,而是直接用in d就可以了!

Dictionary get Method

在向字典中添加key时,常常要判断原来的key是否存在。如果仅仅是对原来的值做一些操作,那么get方法就非常适合。

get(key,default):获取key的值,如果key不存在,则返回default。

Dictionary setdefault Method

上一节是获取,那么相应的会有设置。setdefault的语义是”set if necessary, the get”,首先会判断key是否存在,如果不存在则设置值,否则返回已存在的值。在cookbook一书中,它提到这一函数对于值为链表的字典很有用。

defaultdict

它是从字典中派生出来的,顾名思义,这种字典有一个默认的值(事实上它通过一个函数)。这个种字典的产生来源于简化setdefault的调用,在以后遇到使用setdefault时,可以考虑使用这个特化的字典代替。

PS:这个类来源于collections模块,这个模块还包含其它有用模块,包括队列、OrdereDict、MutableSet等。

Building Dictionary

将2个序列组合在字典:一个序列为键,别一个为值。这种操作有一个惯用法,即使用zip组合。

given = ['John', 'Eric', 'Terry', 'Michael']
family = ['Cleese', 'Idle', 'Gilliam', 'Palin']
pythons = dict(zip(given, family))

Test for Truth Values

Python中不喜欢在条件判断时与True或False做比较,而是直接用内置转换和not来判断。这样做代码更简练。下面是判断True与False的完整表格。

False

True

False (== 0)

True (== 1)

"" (empty string)

any string but "" (" ", "anything")

0, 0.0

any number but 0 (1, 0.1, -1, 3.14)

[], (), {}, set()

any non-empty container ([0], (None,), [''])

None

almost any object that's not explicitly False

Index & Item:enumerate

enumerate函数很大的特点是这是个generator函数,所以在一些场合效率会不错。在涉及Index时,这个函数应该是用得最多的。因为
Python语言中for循环的天生缺陷,如果要达到这个效果,必须用range,并再配合索引。正因为这个缺陷,才有了这个函数产生!这给我的感觉就像
STL很多人推荐用迭代器遍历,有人觉得声明太冗长,于是在C++0x推出一个auto关键字来。

Default Parameter Values

一开始出现了一个非常令人不解的代码

def bad_append(new_item, a_list=[]):
    a_list.append(new_item)
    return a_list
>>> print bad_append('one')
['one']
>>> print bad_append('two')
['one', 'two']

问题原因是,a_list是一个变量,它在声明的时候被定义为一个空的list。而list是mutable对象~~~~~~~~~~

最终我找到它的原因。在函数声明时,创建了一个空的list (‘[]’),a_list只不过是这个空list的Label而已。在编译器中,a_list被定死为某一全局list的地址“引用”。在第一次调用 append(‘on’)时,那个空list变成了[‘one’],函数退出后此list没有回收,所以在下一次调用时才会出现这种情况!

Advanced % String Formatting

%有一个非常有意思的用法,即在字符串内写出对象名字。

values = {'name': name, 'messages': messages}
print ('Hello %(name)s, you have %(messages)i ' % values)

这种写法的好处是,当要改变打印格式时,只需要改变里面的内容即可。通常,values是用locals()代替,这样一来这种灵活的机制就非常厉害了。例如,可以向某一函数传入一条字符串就可以指定打印的内容了。

Generator Expression(生成器表达式)

GE与listcomprehension(列表解析)非常类似

列表解析:
语法:[expr for iter_var in iterable] 或 [expr for iter_var in iterable ifcond_expr]

生成器表达式:
语法:(expr for iter_var in iterable) 或 (expr for iter_var in iterable if cond_expr)

生成器表达式比列表解析晚一点出来,它的好处非常明显,就是它返回的是一个“生成器”,而非一个列表。

生成器在Python中被推荐替代常规的for循环,而很多地方生列表施展的地方成器也可以替代,因为本质上它们支持程度相同。当列表仅仅是作为临时使用时,生成器可能在内存上表现更佳。

Reading Lines From Text/Data File

请看代码

datafile = open('datafile')
for line in datafile:
    do_something(line)

可能不少人会使用readlines方法,对于小文件,两者没有区别,但是大文件前者效率会高很多。

Python——Code Like a Pythonista: Idiomatic Python的更多相关文章

  1. 《Writing Idiomatic Python》前两部分的中文翻译

    汇总了一下这本小书前两部分的内容: 翻译<Writing Idiomatic Python>(一):if语句.for循环 翻译<Writing Idiomatic Python> ...

  2. 翻译《Writing Idiomatic Python》(五):类、上下文管理器、生成器

    原书参考:http://www.jeffknupp.com/blog/2012/10/04/writing-idiomatic-python/ 上一篇:翻译<Writing Idiomatic ...

  3. 翻译《Writing Idiomatic Python》(一):if语句、for循环

    开篇废话 这是在美国Amazon上评价很不错的一本书,其实严格来说这可能不算书,而是一本小册子.就像书名一样,里面的内容主要是用一些例子讲述地道的Python的代码是怎样写的.书中把很多例子用不良风格 ...

  4. 翻译《Writing Idiomatic Python》(二):函数、异常

    原书参考:http://www.jeffknupp.com/blog/2012/10/04/writing-idiomatic-python/ 上一篇:翻译<Writing Idiomatic ...

  5. 翻译《Writing Idiomatic Python》(四):字典、集合、元组

    原书参考:http://www.jeffknupp.com/blog/2012/10/04/writing-idiomatic-python/ 上一篇:翻译<Writing Idiomatic ...

  6. 翻译《Writing Idiomatic Python》(三):变量、字符串、列表

    原书参考:http://www.jeffknupp.com/blog/2012/10/04/writing-idiomatic-python/ 上一篇:翻译<Writing Idiomatic ...

  7. 分享书籍[writing idiomatic python ebook]

    你是不是总是觉得学了python好久,蓦然回首,总是感觉写的代码不是那么有pythonic的味道.看看别人的代码(django,webpy),再看看自己的代码,觉得就是一java-python的混合体 ...

  8. Exploring Python Code Objects

    Exploring Python Code Objects https://late.am/post/2012/03/26/exploring-python-code-objects.html Ins ...

  9. 机器学习算法实现(R&Python code)

    Machine Learning Algorithms Machine Learning Algorithms (Python and R) 明天考试,今天就来简单写写机器学习的算法 Types Su ...

随机推荐

  1. String、ANSIString、PChar及TBytes之间的转换 BytesOf move stringof

    一.string转为ansistring 1.直接赋值 (有警告)2.ansistring()类型强制转换.(无警告) 二.ansistring 转为string 1.直接赋值 (有警告)2.stri ...

  2. 剑指offer 面试题5 : 从尾到头打印链表

    题目: 输入一个链表的头结点,从尾到头反过来打印出每个节点的值.链表结点定义如下: struct ListNode { int m_nKey; ListNode* m_pNext; }; 思路: 通常 ...

  3. Selenium2+python自动化70-unittest之跳过用例(skip)【转载】

    前言 当测试用例写完后,有些模块有改动时候,会影响到部分用例的执行,这个时候我们希望暂时跳过这些用例. 或者前面某个功能运行失败了,后面的几个用例是依赖于这个功能的用例,如果第一步就失败了,后面的用例 ...

  4. 为用户分配角色 C#

    开发网站时,在后台管理系统中,如果有多类角色,将会涉及到为角色分配用户的功能,或者是为用户选择角色.为用户分配角色相对来说操作的数据量比较小,因为系统所设定的角色不会有很多种.而如果是为角色分配用户, ...

  5. DB2 v9.7官方下载链接

    http://blog.sina.com.cn/s/blog_8ea8e9d50102w2s6.html

  6. [libgdx游戏开发教程]使用Libgdx进行游戏开发(3)-给游戏添加一些控制功能

    每个游戏中都有一些只有程序员自己才知道的控制功能,比如增加金钱,满血复活,无视防御,不死等等. 都是为了方便自己调试而在测试阶段使用的功能. 正如上一章提到的:我们也需要加些只有程序员才知道的控制功能 ...

  7. basic paxos解析

    basic paxos是我见过最难懂的算法,我最近一个月都在研究这个东西,自认有一些粗浅的心得,在这里写一下我对它的理解 为了降低理解难度,本文使用了大量的比喻,可能词不达意,见谅 basic pax ...

  8. 漫谈网络通信——从OSI网络模型到TCP/IP协议族

    OSI七层模型 OSI(Open System Interconnection,开放系统互联)七层网络模型成为开放式系统互联参考模型,是一个把网络通信在逻辑上的定义,也可以理解成为定义了通用的网络通信 ...

  9. 使用moneykey对APP进行健壮性测试

    注意:moneykey对app按钮伪随机点击,只能测试app稳定性和健壮性,无法进行常规测试 1.安装 A.jdk(不详细介绍) B.安装配置android配置环境:Android Studio 此环 ...

  10. asp.net中利用JSON进行增删改查中运用到的方法

    //asp.net中 利用JSON进行操作, //增加: //当点击“增加链接的时候”,弹出增加信息窗口,然后,在窗体中输入完整信息,点击提交按钮. //这里我们需要考虑这些:我会进行异步提交,使用j ...