扩展Python装饰器的功能

回忆setattr和getattr

我们都知道setattr和getattr操作是我们操作某个对象时获取对象属性,或者给某个对象设置属性来用的

class Test(object):
    def __init__(self):
        self.name = 'haha'


test = Test()
print(getattr(test, 'name'))
setattr(test, 'age', 16)

print(getattr(test, 'age'))
print(test.age)

可以看到我们用getattr和对象名.属性名一样可以获取到对应的属性值。很有可能我们需要添加的属性的名称是个变量,而不是写死的,也就是说是可配置的。这个时候就不能通过.了,我们考虑问题的时候不能仅仅从功能入手,也需要思考一下它的使用场景。

扩展装饰器的功能

你面临一个变动很频繁的业务,你无法预知之后的需求情况,想要代码有足够大的机动余地,这个时候可以利用强大的setattr给程序留一个“后门”,方便后面临时修改。
具体的做法其实很简单,我们在装饰器当中定义一个dict,用来存储自定义的函数。再实现一个set_func方法将自定义的函数存储进这个dict当中,只有就可以通过参数,在不修改装饰器的情况下自由变更装饰器内的逻辑了。

#def attach(obj, func=None):
#     if func is None:
#         return partial(attach, obj)
#     setattr(obj, func.__name__, func)
#     return func

def attach(obj):
    @wraps(obj)
    def wrapper(func):
        setattr(obj, func.__name__, func)
        return func

    return wrapper


def decorate(func):
    func_dict = {
    
    }

    @wraps(func)
    def wrapper(*args, **kwargs):
        # 通过key来选择应该调用哪一个函数作为装饰器的逻辑
        if kwargs.get('key') is not None:
            func_dict[kwargs['key']](*args, **kwargs)
        return func(*args, **kwargs)

    # 将函数名和函数作为参数传入,存储在dict中
    @attach(wrapper)
    def set_func(func_name, func):
        nonlocal func_dict
        func_dict[func_name] = func

    return wrapper


def test(*args, **kwargs):
    print('8888888')


@decorate
def add(a, b, key=None):
    print('111111111')


add.set_func('test', test)
add(3, 4, key='test')

这样,我们就把test方法中的逻辑放入了装饰器当中,只有我们需要,我们还可以写出其他的方法,来自定义我们对装饰器的需求,而又不需要修改装饰器内部的逻辑。不仅如此,我们还可以在主体函数的前后都加上这样的逻辑。

猜你喜欢

转载自blog.csdn.net/mingtiannihaoabc/article/details/106175455