在装饰器中使用functools.partial,将函数作为对象的属性附加

时间:2018-01-04 15:35:42

标签: python decorator

Python Cookbook 部分9.5. Defining a Decorator with User Adjustable Attributes中,我在以下代码中使用functools.partial时遇到了困难:

# Utility decorator to attach a function as an attribute of obj
def attach_wrapper(obj, func=None):
    if func is None:
        return partial(attach_wrapper, obj)
    setattr(obj, func.__name__, func)
    return func

如果组合多个装饰器,是否可以防止属性阴影?我并不完全清楚为什么会在这里使用偏爱,并希望得到任何澄清。

1 个答案:

答案 0 :(得分:3)

我会尝试两种解释。这是短篇小说。这些装饰器是等价的。

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


def my_attach_wrapper(obj):
    def wrapper(func):
        setattr(obj, func.__name__, func)
        return func
    return wrapper

这是长版本。这是包装器所做的一步一步。

@attach_wrapper(wrapper)
def set_level(newlevel):
    level = newlevel

相当于:

def set_level(newlevel):
   level = newlevel

set_level = attach_wrapper(wrapper)(set_level)

首先,attach_wrapper(wrapper, func=None)返回一个带有一个参数func的部分函数。为简单起见,我们调用这个新函数partial_attach。我们可以像这样定义它:

def partial_attach(func):
    setattr(wrapper, func.__name__, func)
    return func

attach_wrapper(wrapper, func=None)返回partial_attach时,我们有:

set_level = partial_attach(set_level)

因为返回set_levelset_level等于它自己。但现在wrapper有一个属性set_level,它指向同一个函数。