一些pythonic代码的例子

##百分号的使用:
通常我们都是这样格式化字符串的:

print 'hello world programme by %s' % 'python'  

但是如果格式化的字符串中有很多%s,那么程序的可读性就会依靠于%后面 的变量名起得是否好了。

这个时候有一种用dict来格式化的%,我觉得很有用,尤其是在记log的 时候,作为log的格式,可读性非常高。
代码如下:

#字符串  
value = {'what': 'hello, world', 'language': 'python'}  
print '%(what)s, %(language)s' % value  
#也可以包含int的  
value = {'name': 'jianpx', 'age': 23}  
print '%(name)s 's age is  %(age)i' % value

用两个元素之间有对应关系的list构造一个dict:

运用zip可以非常简单的实现:

names = ['jianpx', 'yue']  
ages = [23, 40]  
m = dict(zip(names,ages))  

zip的使用可以help(zip)或者查看官方文档。

##交换两个值:
在其他语言可能要一个临时变量和三句话:

temp = a
a = b
b = temp

但是在python,一句就ok了,而且不需要临时变量:

a,b = b,a

右边的b,a 其实可以理解成一个tuple。

##数量多的字符串相连用join:
python字符串效率问题之一就是在连接字符串的时候使用‘+’号,例如 s = 's1' + 's2' + 's3' + ...+'sN',总共将N个字符串连接起来,但是使用+号的话,python需要申请N-1次内存空间,然后进行字符串拷贝。原因是字符串对象PyStringObject在python当中是不可变对象,所以每当需要合并两个字符串的时候,就要重新申请一个新的内存空间(大小为两个字符串长度之和)来给这个合并之后的新字符串,然后进行拷贝。所以用+号效率非常低。建议在连接字符串的时候使用字符串本身的方法join(list),这个方法能提高效率,原因是它只是申请了一次内存空间,因为它可以遍历list中的元素计算出总共需要申请的内存空间的大小,一次申请完。所以上面的例子可以写成s = ''.join(['s1','s2',....,'sN'])

例子是:

#以前是这样写的  
fruits = ['apple', 'banana']  
result = ''  
for f in fruits:  
    result += f  

#现在可以这样:  
fruits = ['apple', 'banana']  
result = ''.join(fruits)  

##判断一个key是否在一个dict里面:
以前很经常犯的一个mistake是这样做:

if key in dict_example:  
    do something  

现在要这样写,就不用使用in操作了。

if dict_example.has_key(key):  
    do something  

##去掉list中的重复元素:

old_list = [1,1,1,3,4]  
new_list = list(set(old_list))  

##判断元素是否在列表中
如果对没有重复元素的列表对象,要判断某个元素是否在列表里面的话,当这个列表很大的时候,用set会比list
的性能要好,因为对于list,本身允许重复元素存在,所以它不是用hash实现的,但是set不一样,它不允许重复元素,看了python源代码,从set的实现源码setobject.c 中查找key的函数

static setentry *
set_lookkey(PySetObject *so, PyObject *key, register long hash)    

的接口可以看出它真的使用hash去实现的。

所以对于in操作,set的实现是计算这个元素的hash值然后判断,理论上可以达到O(1)

##读文件操作:
以前是这样写的:

#默认文件存在,不处理Exception的情况  
f = open('filename', 'r')  
while 1:  
    line = f.readline()  
    if not line:  
        break  
    print line  

if f:  
    f.close()  

用with关键字可以这样简写了,

from __future__ import with_statement  
with open('filename','r') as f:  
    for line in f:  
        print line  

具体关于with的可以参考这篇文章

##输出数组的index和值:
以前是要这样写的:

l = [1,3,4]  
for i in xrange(len(l)):  
    print '%d, %d' % (i , l[i])  

现在可以用enumerate函数帮助你简写:

l = [1,3, 4]  
for index, value in enumerate(l):  
    print '%d, %d' % (index, value)  

##关于使用map、filter、reduce的例子网上很多,这里不细说了,它们的使用也是pythonic的examples

##分隔一个字符串,去里面的元素,但是空白字符串不要:
例如, names = ‘jianpx, yy, mm, , kk’

names = 'jianpx, mm, yy, , kk'  
name_list = names.split(',')  
result = []  
for name in name_list:  
    if name:  
        result.append(name)  

现在是这样写的:

names = 'jianpx, yy, mm, , kk'  
result = [name for name in names.split(',') if name.strip()]  

##模拟c语言中的 a?b:c
在python里面可以这样做:

return_value = True if a == 1 else False  

从而代替了这样的代码:

if a == 1:  
    return_value = True  
else   
    return_value = False  

##用Decorator抽离公用代码或者解耦
例如要对一个函数做cache,对一个操作限制权限,如果需求随时可能变化,就是说有可能不需要做cache或者不需要做权限的时候,你如果把实现放到这些函数体里面,那么这时你必须把这些代码删除,而且要很小心。但是如果你用Decorator去做的话, 只要删除函数头顶上的@那一行就可以了。Django经常用这种方法做权限控制。
熟悉decorator的应该都很容易理解。

##如何将list的元素倒序并且生成到新的list呢?

看到一个用list的slice做到的 :

a = [1,2,3,4]  
c = 'abcdef'  
aa= a[::-1]  
cc = c[::-1]  

如果不用生成新的list,直接调用a.reverse()就得了。但是字符串类型没有reverse的方法.

关于list的slice特性, 其实也许很多人平时只是用list[start:end] 这样的, 这个意思是从start开始,每个元素都放到新的list里面, 直到end。但是其实还可以每隔N个元素才取一次的, 这种情况要3个参数:·list[start:end:step]step就是间隔了。

##a = [i for i in xrange(5)] 和 a = (i for i in xrange(5))

虽然看上去是一样都生成了5个元素,但是
前者是一个list对象, 如果遍历的话 for item in a 就会一下子返回全部元素然后再遍历, 而后者是个Generator,
用for item in a遍历是每次只是返回一个元素, 这样的好处是省内存(在list很大的情况下)。

##python的all函数可以简化逻辑表达式有很多”与“的时候的写法
比如:

a, b, c = True, False, True
if a and b and c:
    return True
else:
    return False
可以简化成:
    return all([a, b, c])

由此可以看到all函数的作用是判断当且仅当参数里面都为真的时候返回真, 否则返回假。

但是这里更深入的话涉及all的判断顺序和传入的参数是list还是iterable对象是不同的。