19.3-装饰器习题cache和命令分发器实现

当你处于低潮期的时候,好好想想,就算现在攒不到钱,攒点知识,交情,经验,最不济攒点教训也行!

装饰器一定要多加练习,装饰器是越练越熟练;后面很多框架一装饰就能用了,
经常见到的各种类型的装饰器都要练一遍;

本章总结:

  1. 无参、有参、缓存装饰器、通用装饰器、 1.40;
  2. 装饰器是AOP面向对象编程 Aspect Oriented Programming思想的体现
  3. 想装饰器 return 是什么 很重要,
装饰器

装饰器(Decorator)是python的一个重要部分,简单来说,他是修改其他函数功能的函数。

它是一种不修改原来的业务代码,给程序动态添加功能的技术;例如logger函数功能就是对业务函数增加日志的,而业务函数中应该吧业务无关的日志玻璃干净;

他们有助于让我们的代码更简短,也更Pythonic!

解除装饰器:
可以访问 _wrapped_属性来访问原始函数

orig_add = add.__wrapped__
orig_add(1,2)

装饰器应用场景
日志、监控、权限、设计、参数检查、路由等处理
这些功能与业务功能无关,很多业务都需要的公有的功能,所以适合独立出来,对目标对象进行增强;

1. 缓存装饰器实现;


from functools import wraps
import inspect,datetime

def mag_cache(fn):
    local_cache = {}
    @wraps(fn)
    def wrapper(*args, **kwargs):
        # 参数处理,构建key
        sig = inspect.signature(fn)  
        params = sig.parameters
        
        params_dict = {}
        
        values = list(params.values())
        keys = list(params.keys())
        
        # 位置和关键字传参
        params_dict.update(zip(params.keys(),args))
        params_dict.update(kwargs)
        
        # 缺省值
        for k,v in params.items():
            if k not in params_dict:
                params_dict[k] = v.default
                
        key = tuple(sorted(params_dict.items()))
        print(key)
        
        if key not in local_cache.keys():
            local_cache[key] = fn(*args,**kwargs)
        
        return local_cache[key]
    return wrapper

@mag_cache
def add(x,y,z=6):
    datetime.sleep(2)
    return x+y+z

2.命令分发器实现
# 1 基本框架
# 第一个版本:
commands = {}

def reg(cmd, fn):
    commands[cmd] = fn

def defaultfn():
    print("Unknown command")
    
def foo1():    # 硬编码
    print('magedu')
    
def foo2():   # 硬编码
    print('python')
reg('mag', foo1)
reg('py', foo2)
    
def dispatcher():
    while True:
        cmd = input('>>>').strip()
        if cmd == '':
            print('bye')
            return
        commands.get(cmd, defaultfn)()

dispatcher()
-------------------------------------
>>>mag
magedu
>>>py
python
>>>
bye


# 2 柯里化变有参
commands = {}

def reg(cmd):
    def _reg(fn):
        commands[cmd] = fn
        return fn
    return _reg

def defaultfn():
    print("Unknown command")

@reg('mag')
def foo1():
    print('magedu')
   
@reg('py')
def foo2():
    print('python')
#reg('mag', foo1)
#reg('py', foo2)
    
def dispatcher():
    while True:
        cmd = input('>>>').strip()
        if cmd == '':
            print('bye')
            return
        commands.get(cmd, defaultfn)()

dispatcher()
-------------------------------------
>>>mag
magedu
>>>py
python
>>>
bye



# 3 函数封装
def cmds_dispatcher(defaultfn=lambda :print('Unknown command')):
    commands = {}

    def reg(cmd):
        def _reg(fn):
            commands[cmd] = fn
            return fn
        return _reg

    #def defaultfn():
    #    print("Unknown command")

    def dispatcher():
        while True:
            cmd = input('>>>').strip()
            if cmd == '':
                print('bye')
                return
            commands.get(cmd, defaultfn)()
            
    return reg,dispatcher
        
reg, dispatcher = cmds_dispatcher()
        
@reg('mag')
def foo1():
    print('magedu')
   
@reg('py')
def foo2():
    print('python')
#reg('mag', foo1)
#reg('py', foo2)

dispatcher()

你可能感兴趣的:(19.3-装饰器习题cache和命令分发器实现)