Python装饰器可选参数

标签 python decorator

from functools import wraps
def logged(func):
    @wraps(func)
    def with_logging(*args, **kwargs):
        print func.__name__ + " was called"
        return func(*args, **kwargs)
    return with_logging

@logged
def f(x):
   """does some math"""
   return x + x * x

print f.__name__  # prints 'f'
print f.__doc__   # prints 'does some math'

鉴于此示例代码,我将如何执行 @logged(variable)

我试过了

from functools import wraps
def logged(func):
    def outer(var):
        @wraps(func)
        def with_logging(*args, **kwargs):
            print func.__name__ + " was called"
            return func(*args, **kwargs)
        return with_logging
    return outer

我希望像这样执行:logged(func)(session_variable)

但是不起作用。 任何的想法?我希望能够执行@logged 和@logged(var)(甚至@logged(var1, var2)) 谢谢。

最佳答案

这里的诀窍是,你必须反省你得到的东西:

def logged(*setting_args, **setting_kwargs):
    no_args = False
    if len(setting_args) == 1 \
        and not setting_kwargs \
        and callable(setting_args[0]):
        # We were called without args
        func = setting_args[0]
        no_args = True

    def outer(func):
        @wraps(func)
        def with_logging(*args, **kwargs):
            print "{} was called".format(func.__name__)
            print "Setting args are: {}".format(setting_args)
            print "Setting keyword args are: {}".format(setting_kwargs)
            return func(*args, **kwargs)
        return with_logging

    if no_args:
        return outer(func)
    else:
        return outer

这将适用于以下任何一项:

# No arguments
@logged
def some_function(x):
    pass

# One or more arguments
@logged(1, 2, 3)
def some_function(x):
    pass

# One or more keyword arguments
@logged(key=1, another_key=2)
def some_function(x):
    pass

# A mix of the two
@logged(1, 2, key=3)
def some_function(x):
    pass

如果只用一个可调用参数调用它,它将不会工作:

# This will break.
@logged(lambda: "Just for fun")
def some_function(x):
    pass

无法区分单个可调用设置和装饰器的无参数调用之间的区别。但是,如果需要,您可以传递一个垃圾关键字 arg 来解决这个问题:

# This gets around the above limitation
@logged(lambda: "Just for fun", ignored=True)
def some_function(x):
    pass

关于Python装饰器可选参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17119154/

相关文章:

python - as_view()(对于基于类的 View )可以在装饰器中实现吗?

python - @property 和 property() 的区别

Python:修饰的静态方法接收不可调用的方法

Python 并没有明显的方法从字典中获取特定元素

python - 在列表中创建重复项

python - 像访问常规列一样访问 Pandas 索引

javascript - ES7 装饰器在设置了 "displayName"的类上不起作用

python - 从 python 实现 R 包 TSdist

python - 如何将列表中的某些分数分配给多个列表中的值并获取 python 中每个值的总和?

Python 更改方法名称