Code Like a Pythonista: Idiomatic Python
如果你有C++基础,那学习另一门语言会相对容易。因为C++即面向过程,又面向对象。它很底层,能像C一样访问机器;它也很高级,有模板、STL等。如果认真读过《深入C++对象模型》,我想其它语言不会比这个更复杂。你对C++了解的越深,你用其它语言写出的代码就越像C++,这样就体现不出新语言的价值了。所以,学习新语言要抛弃原有的潜意识,包括代码风格。
漂亮比丑陋好
清晰比隐含好
简单比复杂好
复杂比晦涩好
平摊比嵌套好
松耦合比紧耦合好
可读性是有价值的
特殊的条件不足以打破这些条款
尽管实践打败理论的纯洁
错误永远不要掩盖
除非明确地平息它
……
Python倡导使用_internal来表示私有属性,它没有命令空间限制,而仅仅是善意提醒“be careful with this, it's an internalimplementation detail; don't touch it if you don't fully understand it”
def __init__(self, first, second, third, fourth, fifth, sixth): output = (first + second + third + fourth + fifth + sixth)其它换行要使用“\”,注意后面千万不要有空格
Python中不提倡将多条语句写在同一行。比如if语句等。Python是非常讲究通过缩进来显示代码的结构与流程。
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
>>> 1, (1,)即使上面没有括号也无妨。
colors = ['red', 'blue', 'green', 'yellow'] result = '' for s in colors: result += sresult = ''.join(colors) #这一条要比上面for循环更有效率
作者一再强调,字典重载的in操作是对象是所有的keys,所以没必要先调用d.keys()获取键的列表,再使用in,而是直接用in d就可以了!
get(key,default):获取key的值,如果key不存在,则返回default。
PS:这个类来源于collections模块,这个模块还包含其它有用模块,包括队列、OrdereDict、MutableSet等。
given = ['John', 'Eric', 'Terry', 'Michael'] family = ['Cleese', 'Idle', 'Gilliam', 'Palin'] pythons = dict(zip(given, family))
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 |
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没有回收,所以在下一次调用时才会出现这种情况!
values = {'name': name, 'messages': messages} print ('Hello %(name)s, you have %(messages)i ' % values)这种写法的好处是,当要改变打印格式时,只需要改变里面的内容即可。通常,values是用locals()代替,这样一来这种灵活的机制就非常厉害了。例如,可以向某一函数传入一条字符串就可以指定打印的内容了。
列表解析:
语法:[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循环,而很多地方生列表施展的地方成器也可以替代,因为本质上它们支持程度相同。当列表仅仅是作为临时使用时,生成器可能在内存上表现更佳。
datafile = open('datafile') for line in datafile: do_something(line)可能不少人会使用readlines方法,对于小文件,两者没有区别,但是大文件前者效率会高很多。