使用装饰器来调用不带参数的函数

时间:2019-03-09 08:30:46

标签: python decorator python-decorators

为了使我的代码更清晰(大部分)让我自己阅读,我尝试使用修饰符将大多数函数参数放入@decorator(args)内,然后调用不带参数的函数。这是我当前的代码:

def dec1(*args, **kwargs):
    def dec2(func):
        return func(*args, **kwargs)
    return dec2

@dec1(1, 2, 3)
def func1(val1, val2, val3):
    print(val1)
    print(val2)
    print(val3)

if __name__ == "__main__":
    func1()

但是,它正在报告此消息(本质上是使用装饰器运行代码,而不是第二个函数调用):

1
2
3
Traceback (most recent call last):
  File "/home/shadowrylander/decorator_test.py", line 13, in <module>
    f1()
TypeError: 'NoneType' object is not callable

我正在尝试完成的工作与Click库所做的工作类似(用参数定义hello(),然后再不调用它):

import click

@click.command()
@click.option('--count', default=1, help='Number of greetings.')
@click.option('--name', prompt='Your name',
              help='The person to greet.')
def hello(count, name):
    """Simple program that greets NAME for a total of COUNT times."""
    for x in range(count):
        click.echo('Hello %s!' % name)

if __name__ == '__main__':
    hello()

如果有人可以帮助我创建与此类似的装饰器,我将不胜感激,如果在此之前已经有人问过和/或回答过这个问题,我深表歉意;我或者无法正确理解它们,或者找不到问题!
谢谢您的帮助!

1 个答案:

答案 0 :(得分:1)

dec2中,您将返回使用指定参数调用func1的结果,这不是您想要的。

您想要返回一个函数f,该函数使用指定的参数调用func1,即:

def dec1(*args, **kwargs):
    def dec2(func):
        def f():
            return func(*args, **kwargs)
        return f
    return dec2

更详细的解释:

请记住装饰器语法:

@dec1(1, 2, 3)
def func1(val1, val2, val3):
    ...

在语法上等同于:

def func1(val1, val2, val3):
    ...
func1 = dec1(1, 2, 3)(func1)

因此,在装饰函数时,以装饰函数(dec1(...))作为参数调用dec2func1)的结果。因此,您不希望dec2做任何事情,而是返回一个函数,该函数在调用后会做某事。