1,列表推导(没当要对序列中的内容进行循环处理时,就应该尝试使用列表推倒)
在python中编写如下的代码是让人痛苦和不高效已经简洁美观的。
numbers = range(10) evens = [] for i in numbers: if i % 2 == 0: evens.append(i) print evens
毫无疑问,在python中它确实会使得程序的执行速度变得慢了(它使解释程序在每次循环中都要确定序系中哪一部分被修改)
列表推倒是这种场景下的争取选择,它使用编排好的特性对前述语法中的一部分进行了自动化处理:
events = [i for i in range(10) if i % 2 == 0]
这种编写的方法除了高效之外,也更加简短,涉及的元素也更少。在更大的程序中,这意味着引入的缺陷更少,代码更加容易阅读和理解。
2,使用枚举(enumerate)
比如下面的代码就可以换成使用枚举:
i = 0 seq = ['one','two','three'] for element in seq: seq[i] = '%d:%s' % (i,seq[i]) i += 1 print seq
seq = ['one','two','three'] for index,element in enumrate(seq) seq[i] = '%d:%s' % (index,element) print seq
也可以结合一个列表推倒将其重构如下:
def _treatment(pos,element): return '%d:%s' % (pos,element) seq = ['one','two','three'] seq = [_treatment(index,ele) for index,ele in enumrate(seq)] print seq
3,迭代器
迭代器只不过是一个实现迭代协议的容器对象,它基于两个方法:
- next 返回容器的下一个项目;
- __iter__ 返回迭代器本身
创建定制的迭代器:
class My_Iteration(object): def __init__(self,step): self.step = step def next(self): if self.step == 0: raise StopIteration self.step -= 1 def __iter__(self): return self for i in My_Iteration(5): print i
迭代器本身提供了一个底层的概念,它们为生成器这一更有趣的特性提供了基础。
4,生成器(当需要一个将返回一个序列或者在循环中执行的函数时就应该考虑使用生成器)
生成器提供了一个出色的方法,使得需要返回一系列元素的函数所需的代码更加的简单、高效。基于yield指令,可以暂停一个函数并返回中间结果。该函数将保存执行环境并在必要的时候恢复。
生成器对降低程序复杂性也有帮助,并且能够提升基于多个序列的数据转换算法的性能。把每个序列当做一个迭代器,然后将他们合并到一个高级别的函数中,这是一种避免函数变得更加庞大,丑陋,不可理解的好办法,而且,这可以给整个处理链提供实时的反馈。
在下面的例子中,每个函数用来在序列上定义一个转换,然后他们被链接起来应用,每次调用将处理一个元素并返回其结果:
def power(values): for value in values: print 'power %s' % value yield value def adder(values): for value in values: print 'adder %s' % value if value % 2 == 0: yield value + 3 else: yield value + 2 elements = [1,2,3,4,5,7,8] res = adder(power(elements)) #res 就是一个生成器了
5,装饰器(decorator)
装饰器使得函数和方法封装(接受一个函数并返回增强版本的一个函数)更加容易阅读和理解。其实总体说来,装饰器也就是一个函数,一个用来包装函数的函数,返回一个修改之后的函数对象,将其重新赋值原来的标示符,并永久丧失对原始函数对象的访问。
语法:
- 无参数装饰器
def deco(fun): print fun return fun @deco def foo(): pass foo()
第一个函数deco是装饰函数,它的参数就是被装饰的函数对象,我们可以在deco函数内对传入的函数对象做一番“装饰”,然后返回这个对象(一定要返回 ,不然外面调用foo的地方将会无函数可用。实际上此时foo=deco(foo))
下面有个例子检查函数有没有说明文档:
def deco_functionNeedDoc(func): if func.__doc__ == None: print func,"has no __doc__,it's a bad habit." else: print func,":",func.__doc__,"." return func @deco_functionNeedDoc def f(): print 'f() has no doc' #f = deco_functionNeedDoc(f) @deco_functionNeedDoc def g(): 'I have a __doc__' print 'g() has doc' #g = deco_functionNeedDoc(g) f() g()
- 有参数装饰器
def deco_maker(arg): '通常对arg会有一定的要求' """由于有参数的decorator函数在调用时只会使用应用时的参数而不接收被装饰的函数做为参数,所以必须在其内部再创建一个函数""" def newDemo(func):#定义一个新的decorator函数 print func, arg return newDemo return newDemo @deco_maker(deco_args) def foo():pass foo()
第一个函数deco_maker是装饰函数,它的参数是用来加强“加强装饰”的。由于此函数并非被装饰的函数对象,所以在内部必须至少创建一个接受被装饰函数的函数,然后返回这个对象(实际上此时foo=decomaker(arg)(foo))
总结:装饰器可以让函数轻装上阵,更重要的是将函数的约束放置于接口处,使意图更加明了,同时又不增加调用者的负担。
再看一个例子:
import time,logging logger = logging.getLogger() logger.setLevel(logging.DEBUG) is_debug = True def count_time(is_debug): def handle_func(func): def handle_args(*args,**kwargs): if is_debug: begin = time.time() func(*args,**kwargs) logging.debug("[" + func.__name__ + "] -> " + str(time.time() - begin)) else: func(*args,**kwargs) return handle_args return handle_func def pr(): for i in range(1,1000000): i = i * 2 print 'hello world' def test(): pr() @count_time(is_debug) def test2(): pr() @count_time(False) def test3(): pr() if __name__ == '__main__': # f() # g() test() test2() test3()
参考:http://blog.csdn.net/wklken/article/details/8118942
6,with语句
对于确保即使发生错误时也能运行一些清理代码而言,try...finally语句是很有用的,对此有许多的场景,如:
- 关闭一个文件
- 释放一个锁
- 创建一个临时的代码补丁
- 在特殊环境中运行受保护的代码
with语句覆盖了这些使用场景,为在一个代码前后调用一些代码提供了一种简单的方法。例如,文本的读取通常如下实现:
hosts = open('/etc/issus') try: for line in hosts: if line.startswith('#') contine print line finally: hosts.close()
通过使用with语句,以上代码可以重构如下:
from __future__ import with_statement with open('/etc/issue') as hosts: for line in hosts: if line.startswith('#') continue print line