装饰器:
在函数代码功能运行期间动态增加功能的方式叫做装饰器(Decorator)。它对一个函数或者类进行再加工。
我们先定义两个函数,一个计算两数和,一个计算两数差。
1 >>> def square_sum(a,b): 2 ... return a + b 3 ... 4 >>> def square_diff(a,b): 5 ... return a - b 6 ... 7 >>> print(square_sum(3,4)) 8 7 9 >>> print(square_diff(9,5)) 10 4
如果我们想要给这个函数再加其他功能呢,如打印出输入的参数值,我们可能会这样:
1 >>> def square_sum(a,b): 2 ... print 'input:',a,b 3 ... return a + b 4 ... 5 >>> print(square_sum(3,4)) 6 input: 3 4 7 7
在python中,我们可以利用装饰器这么干:
1 >>> def decorator(f): 2 ... def new_f(a,b): 3 ... print 'input',a,b 4 ... return f(a,b) 5 ... return new_f 6 ... 7 >>> @decorator 8 ... def square_sum(a,b): 9 ... return a + b 10 ... 11 >>> @decorator 12 ... def square_diff(a,b): 13 ... return a - b 14 ... 15 >>> print(square_sum(3,4)) 16 input 3 4 17 7 18 >>> print(square_diff(9,5)) 19 input 9 5 20 4
在上面的例子中,装饰器接受一个函数作为输入参数,并返回一个新的函数,装饰器新建了一个可用函数new_f,在这个函数中我们增加了打印功能,并通过调用之前的函数f来实现原来函数的功能。当我们在调用square_sum(3,4)的时候就等同于
square_sum = decorator(square_sum)
square_sum(3,4)
这样的好处是提高了代码的可复用性!
在上面的装饰器中,它默认他后面的函数是他的唯一参数,如果我们想传其他参数怎么办呢,比如@decorator(a),我们可以这样:
1 >>> def pre_str(pre=''): #一层新函数 2 ... def decorator(f): #原来的装饰器 3 ... def new_f(a,b): 4 ... print(pre + "input", a, b) 5 ... return f(a,b) 6 ... return new_f 7 ... return decorator 8 ... 9 >>> @pre_str('balabala') 10 ... def square_sum(a,b): 11 ... return a+b 12 ... 13 >>> print(square_sum(3,4)) 14 ('balabalainput', 3, 4) 15 7
装饰类:
一个装饰类可以接收一个类,并返回一个类,起到加工类的效果!
1 >>> def decorator(aClass): 2 ... class newClass: 3 ... def __init__(self,age): 4 ... self.total_display = 0 5 ... self.wrapped = aClass(age) 6 ... def display(self): 7 ... self.total_display += 1 8 ... print "total display",self.total_display 9 ... self.wrapped.display() 10 ... return newClass 11 ... 12 >>> @decorator 13 ... class Bird: 14 ... def __init__(self,age): 15 ... self.age = age 16 ... def display(self): 17 ... print "My age is",self.age 18 ... 19 >>> eagleLord = Bird(5) 20 >>> for i in range(3): 21 ... eagleLord.display() 22 ... 23 total display 1 24 My age is 5 25 total display 2 26 My age is 5 27 total display 3 28 My age is 5
生成器:
生成器是为了避免构造一个超大的列表,是一边循环一边计算的机制!
1 >>> L = [x * x for x in range(10)] 2 >>> L 3 [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] 4 >>> g = (x * x for x in range(10)) 5 >>> g 6 <generator object <genexpr> at 0x02140620> 7 >>> g.next() 8 0 9 >>> g.next() 10 1
generator保存的是算法,每次都需要调用next来进行计算出下一个元素的值,是可迭代的,我们可以通过for来访问他。在函数中可以用yield进行中断输出!
上下文管理器:
用于规定某个对象的适用范围,类比于using(){} 在python中是 with...as...
1 # without context manager 2 f = open("new.txt", "w") 3 print(f.closed) # whether the file is open 4 f.write("Hello World!") 5 f.close() 6 print(f.closed) 7 8 9 # with context manager 10 with open("new.txt", "w") as f: 11 print(f.closed) 12 f.write("Hello World!") 13 print(f.closed)
上面两断代码执行的操作是一样的,通过with as 在超出范围之后自动进行了f的释放!