Python装饰器可选参数 [英] Python decorator optional argument

查看:122
本文介绍了Python装饰器可选参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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(变量)

Given this sample code, how would I be able to do @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

我希望这样执行:logging(func)(session_var iable)

I was hoping to execute like this: logged(func)(session_variable)

但无效。
有什么想法吗?我希望能够执行@logged和@logged(var)(甚至@logged(var1,var2))
谢谢。

But doesn't work. Any idea? I want to be able to do @logged and @logged(var) ( or even @logged(var1, var2)) Thanks.

推荐答案

这里的窍门是,您必须自省给您的内容:

The trick here is, you have to introspect what you are given:

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

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

This will work with any of the following:

# 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

如果仅使用一个可调用的参数调用它将无法正常工作:

It will not work if it is called with only one callable argument:

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

无法分辨单个可调用设置与装饰器的无参数调用之间的区别。但是,即使您需要,也可以传递垃圾关键字arg来解决该问题:

There is no way to tell the difference between a single callable setting and a no-arg invocation of the decorator. However, you can pass a garbage keyword arg to get around even that if you need to:

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

这篇关于Python装饰器可选参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆