理解装饰器:返回类型是未指定参数时的函数

时间:2015-06-15 21:44:53

标签: python decorator python-decorators

我使用单个装饰器来完成两个独立的功能:一个具有装饰器参数的规范;没有它的另一个。

当未传递可选参数时,返回类型是一个函数(具体来说,是装饰器中的int[])。但是,当传递可选参数时,它按预期工作。

你能解释一下这里发生了什么吗?为什么它在这些情况下会有不同的行为?

inner_function

结果:

def cache_disk(cache_folder="./cache"):
    def wrapper(f):
        def inner_function(*args, **kwargs):
            result = f(*args, **kwargs)
            return result
        return inner_function
    return wrapper

@cache_disk
def func1(data):
    return [d for d in data]

@cache_disk(cache_folder='./cache/')
def func2(data):
    return [d for d in data]


data = [1,2,3]
print(func1(data))
print(func2(data))

2 个答案:

答案 0 :(得分:3)

请注意:

@decorator  # no arguments
def func(...):
    ...

相当于:

def func(...):
    ...

func = decorator(func)  # one 'level' of calls

那:

@decorator(...):  # arguments
def func(...):
    ...

相当于:

def func(...):
    ...

func = decorator(...)(func)  # two 'levels' of calls

在第一种情况下,装饰器只有一个参数,func本身。在第二种情况下,装饰器的参数是来自...行的@,它是装饰器返回的函数,用{调用{ {1}}作为论据。

在您的示例中,

func

装饰器@cache_disk def func1(data): ... 获取单个可调用的参数(cache_disk,后者变为func)并返回args[0]。然后当你打电话:

wrapper

print(func1(data)) 获得一个参数(wrapper,后者变为data)并返回f

因此,您有三种选择:

  1. 使用inner_function(注意括号)装饰func1,不将任何参数传递给@cache_disk()本身,将cache_disk传递给func;
  2. 改变wrapper的行为方式取决于它是否传递了一个可调用的参数或其他内容;或
  3. 在评论中指出@o11c,请使用例如cache_disk为无参数版本提供方便的别名,然后使用cache_disk.wrapper = cache_disk()进行装饰。

答案 1 :(得分:1)

如果你想要默认值,你需要调用函数,它返回一个装饰器:

@cache_disk()
def func1(data):
    return [d for d in data]