Python168的学习笔记8

#coding:utf8

#斐波那契数列,第三项起,每一项都等于前两项之和

def memo(func):
    cache = {}#闭包
    def wrap(*args):
        if args not in cache:
            cache[args] = func(*args)
        return cache[args]
    return wrap

@memo
def fibonacci(n):
    if n<=1:
        return 1
    return fibonacci(n-1)+fibonacci(n-2)

#上楼梯算法,总过n个台阶,一次只能迈a-b个台阶,不能后退,问有几种走法
@memo
def climb(n,steps):
    count = 0
    if n==0:
        count = 1
    elif n>0:
        for step in steps:
            count += climb(n-step,steps)
    return count

装饰器的简单应用还是明白的,但是要理解这两个递归算法。

 

关于函数的元数据,如:f.__name__,指的是def时指定的名字;f.__doc__,指的是函数文档字符串;f.__moudle__,指的是函数所属模块;f.__default__,指的是函数默认值;f.__dict__,指的是属性字典;f.__closure__,指的是函数的闭包。。。这些元数据都是func的属性。

使用装饰器可能会改变func的元数据。

#coding:utf8
from functools import update_wrapper,wraps,WRAPPER_ASSIGNMENTS,WRAPPER_UPDATES

def mydecorator(func):
    @wraps(func)#第一种
    def wrapper(*args,**kw):
        '''wrapper function'''
        print 'In wrapper'
        func(*args,**kw)
    #wrapper.__name__ = func.__name__  第二种
    #update_wrapper(wrapper,func,('__name__','__doc__'),('__dict__',))#第四个参数是将func的属性更新到wrap
    #第三种:update_wrapper后两个的默认参数分别是('__module__', '__name__', '__doc__');('__dict__',)
    return wrapper

@mydecorator
def example():
    '''example function'''
    print 'In example'

其实就是对处理后的func的属性进行重新赋回原来的值。

 

定义带参数的装饰器,就是用去判断参数的类型,因为要用过python3的库,所以先略过。

 

修改装饰器的属性。这样的好处是能够在运行中动态修改,而不是每次都要去装饰器处修改。

 

给包裹函数增加一个函数,作为包裹函数的属性,使其可以修改闭包中的自由变量。

 1 import time
 2 from functools import wraps
 3 import logging
 4 
 5 def warn(timeout):
 6     timeout = [timeout]#将参数设为只有一个数的list
 7     def decorator(func):
 8         @wraps(func)
 9         def wrapper(*args,**kw):
10             start = time.time()
11             res = func(*args,**kw)
12             used = time.time()-start
13             if used > timeout[0]:
14                 msg = '%s : %s >%s' %(func.__name__,used,timeout[0])
15                 logging.warn(msg)
16             return res
17         def setTimeout(k):#注意这里
18             timeout[0] = k
19         wrapper.setTimeout = setTimeout
20         return wrapper
21     return decorator
22 
23 from random import randint
24 @warn(0.5)
25 def test():
26     print 'In test'
27     while randint(0,1):
28         print 'I am sleep'
29         time.sleep(1)
30         
31 for _ in range(10):
32     test()
33     
34 test.setTimeout(1)
35 for _ in range(10):
36     test()

 

使用类来定制装饰器。

 1 #coding:utf8
 2 import logging
 3 from time import localtime,time,strftime,sleep
 4 
 5 class CallingInfo(object):
 6     def __init__(self,name):
 7         log = logging.getLogger(name)
 8         log.setLevel(logging.INFO)#设置等级
 9         fh = logging.FileHandler(name+'.log')#设置文件处理方法
10         log.addHandler(fh)#绑定方法到log上
11         log.info('Start'.center(50,'-'))#添加log文本的头部
12         self.log= log#绑定到类的属性上
13         self.formatter = '%(func)s ->[%(time)s - %(used)s -%(ncalls)s]'#定义了输出模板
14         
15     def info(self,func):#这个就是平常的装饰器
16         def wrapper(*args,**kw):
17             wrapper.ncalls +=1
18             lt = localtime()#返回当地时间
19             start = time()
20             res = func(*args,**kw)
21             used = time() - start
22             
23             info = {}#建立info的字典
24             info['func'] = func.__name__
25             info['time'] = strftime('%x %X',lt)
26             info['used'] = used
27             info['ncalls'] = wrapper.ncalls
28 
29             msg = self.formatter % info#将字典映射到输入模板上
30             self.log.info(msg)#输出字符串
31             return res
32         wrapper.ncalls = 0#这个语句需要在这个位置的解释有待完善
33         return wrapper
34     
35     def setFromatter(self,formatter):
36         self.formatter = formatter
37         
38     def turnOn(self):
39         self.log.setLevel(logging.INFO)
40         
41     def turnOff(self):
42         self.log.setLevel(logging.WARN)#级别提高就不在那里输出了    
43         
44 cinfo1 = CallingInfo('mylog1')
45 cinfo2 = CallingInfo('mylog2')
46 
47 cinfo1.setFromatter('%(func)s ->[%(time)s  -%(ncalls)s]')
48 cinfo2.turnOff()#这里可以看到是很方便地修改装饰器
49 
50 @cinfo1.info    
51 def f():
52     print 'in f'
53     
54 @cinfo1.info
55 def h():
56     print 'in h'
57 
58 @cinfo2.info 
59 def g():
60     print 'in g'
61     
62     
63 from random import choice
64 for _ in xrange(10):
65     choice([f,g,h])()
66     sleep(choice([0.5,1,1.5]))

 

posted @ 2016-11-20 13:49  Nanrou  阅读(250)  评论(0编辑  收藏  举报