Python——Code Like a Pythonista: Idiomatic Python

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方法,对于小文件,两者没有区别,但是大文件前者效率会高很多。

时间: 2024-11-05 11:01:11

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

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

原书参考:http://www.jeffknupp.com/blog/2012/10/04/writing-idiomatic-python/ 上一篇:翻译<Writing Idiomatic Python>(四):字典.集合.元组 下一篇:TO BE UPDATED.. 2.7 类 2.7.1 用isinstance函数检查一个对象的类型 许多新手在接触Python之后会产生一种“Python中没有类型”的错觉.当然Python的对象是有类型的,并且还会发生类型错误.比如,对一个int型对象

Exploring Python Code Objects

Exploring Python Code Objects https://late.am/post/2012/03/26/exploring-python-code-objects.html Inspired by David Beazley's Keynote at PyCon, I've been digging around in code objects in Python lately. I don't have a particular axe to grind, nor some

Python code 提取UML

Python是一门支持面向对象编程的语言,在大型软件项目中,我们往往会使用面向对象的特性去组织我们的代码,那有没有这样一种工具,可以帮助我们从已有代码中提取出UML图呢?答案是有的.以下,我们逐个介绍这些工具. pyreverse 是一套python code 逆向工程(reverse engineering)的工具.它使用类层次结构的python 项目表示已提取任何可用的信息,可以很方便的应用于UML图的生成,或者单元测试,如pyargo和py2tests.pyreverse 已被整合进pyl

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

原书参考:http://www.jeffknupp.com/blog/2012/10/04/writing-idiomatic-python/ 上一篇:翻译<Writing Idiomatic Python>(二):函数.异常 下一篇:TO BE UPDATED.. 2.1 变量 2.1.1 对多个变量要赋同一个值时,使用链式赋值让语句变得简明 Python支持链式赋值使多个变量可以在一次链式赋值中被设置为同一个值,这使得语句更加简明. 不良风格: 1 x = 'foo' 2 y = 'foo

Supporting Python 3(支持python3)——欢迎来到Python 3

欢迎来到Python 3 On Christmas Day 1999 I sat down to write my first piece of software in Python. My experience seems to be typical for Python users. I was initially surprised that indentation was significant, it felt scary to not define variables and I w

【Python】初学编程适合学Python?其有何用?

初学编程适合学Python?其有何用? 作者:白宁超 2016年10月4日19:59:39 摘要:python语言俨然不算新技术,七八年前甚至更早已有很多人研习,只是没有现在流行罢了.之所以当下如此盛行,我想肯定是多因素造成了,当然市场需求的重要因素.吴军博士对大数据流行的解释与python流行或许有些默契.数据一直以来都存在,只是在历史条件下,由于计算性能和技术发展的原因,与之匹配的数据处理技术还不是很先进,以至于很多数据被我们舍弃了.同样,python语言简洁流畅等多种优点,也会让第一次接触

《python源码剖析》笔记 Python虚拟机框架

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 1. Python虚拟机会从编译得到的PyCodeObject对象中依次读入每一条字节码指令, 并在当前的上下文环境中执行这条字节码指令. Python虚拟机实际上是在模拟操作中执行文件的过程 PyCodeObject对象中包含了字节码指令以及程序的所有静态信息,但没有包含 程序运行时的动态信息--执行环境(PyFrameObject) 2.Python源码中的PyFrameObject

《python源码剖析》笔记 python虚拟机中的一般表达式

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 1.字节码指令 LOAD_CONST:从consts表中读取序号为i的元素并压入到运行时栈中 STORE_NAME:改变local名字空间.从符号表names取序号为i的元素作为变量名, 取运行时栈的栈顶元素作为变量值,完成从变量名到变量值的映射关系的创建. BUILD_MAP:创建一个空的PyDictObject对象,并压入运行时栈 DUP_TOP:将栈顶元素的引用计数增加1,并将它再次

python源码剖析笔记1——Python对象初见

python源码剖析笔记1--Python对象初见 工作整两年了,用python最多,然而对于python内部机制不一定都清楚,每天沉醉于增删改查的简单逻辑编写,实在耗神.很多东西不用就忘记了,比如C语言,正好,python源码用C写的,分析python源码的同时又能温故C语言基础,实在是件很好的事情.另外,还有陈儒大神的<python源码剖析>做指引,分析也不至于没头没脑.期望在一个月的业余时间,能有所小成,以此为记. 1 python中的对象 python中,一切东西都是对象,在c语言实现