python - 理解装饰器 : return type is a function when argument not specified

标签 python decorator python-decorators

我正在为两个独立的函数使用一个装饰器:一个带有装饰器参数的规范;另一个没有它。

当不传递可选参数时,返回类型为函数(具体为装饰器中的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))

结果:

<function inner_function at 0x7f1f283d5c08>
[1, 2, 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 本身。在第二种情况下,装饰器的参数是 @ 行中的 ...装饰器返回的函数func 作为参数调用。


在你的例子中,

@cache_disk
def func1(data):
    ...

装饰器 cache_disk 获取单个可调用参数(func,变为 args[0])并返回 wrapper 。然后当你打电话时:

print(func1(data))

wrapper 获取单个参数(data,变为 f)并返回 inner_function

因此,您有三个选择:

  1. @cache_disk()(注意括号)修饰func1,不向cache_disk本身和func传递参数> 到包装器
  2. 改变 cache_disk 以根据它是否传递了单个可调用参数或其他参数而表现不同;或
  3. 作为@o11c在评论中指出,使用例如cache_disk.wrapper = cache_disk() 为无参数版本提供方便的别名,然后用 @cache_disk.wrapper 装饰。

关于python - 理解装饰器 : return type is a function when argument not specified,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30855485/

相关文章:

python - Django QuerySet 对象没有属性 'objects

python - 计算单词中的音节数

python - 设置函数属性的装饰器

python - 类方法属性继承

python - Flask:为什么 app.route() 装饰器应该总是在最外面?

python - 如何在 python 中将超时和重试装饰器函数应用于 google-cloud-storage 客户端?

python - 每个训练周期后进行评估

python - pandas DataFrame.query 表达式,默认返回所有行

python - functools.partial 以及它如何组成非关键字参数

java - 像这样使用装饰器模式是不是错了?