python - 将装饰器与可调用对象一起使用时返回用户定义的函数名称

标签 python decorator callable function-object

考虑以下代码片段。

def print_timing(func):
    import time
    def wrapper(*args, **kwargs):
        t1 = time.time()
        res = func(*args, **kwargs)
        t2 = time.time()
        print '%s took %0.3f s ~ %0.0f min and %0.1f sec' % (func.func_name, t2-t1, int(t2 - t1)/60, (t2-t1) % 60 )
        return res
    return wrapper

@print_timing                                                                      |
def foo():                                                                         |
    return 'foo' 

class name(object):
       def __init__(self, name):
              self.name = name
       @print_timing
       def __call__(self):
              return self.name

bar = name("bar")
print bar()

这将返回:

__call__ took 0.000 s ~ 0 min and 0.0 sec
bar

对象 bar 的行为类似于名为 bar 的函数,但与装饰器 一起使用时会公开 __call__ 的内部实现细节打印计时。有没有办法更改 name 对象(也许通过将合适的参数传递给 __init__ 函数),使其返回

 bar took 0.000 s ~ 0 min and 0.0 sec

?我想要一个解决方案,让 print_timing 装饰器继续使用普通函数。运行 print foo() 给出

foo took 0.000 s ~ 0 min and 0.0 sec
foo

最佳答案

只要您仅在方法上使用装饰器,它们就会作为第一个参数传递 self:

def print_timing(func):
    import time
    def wrapper(*args, **kwargs):
        t1 = time.time()
        res = func(*args, **kwargs)
        t2 = time.time()
        funcname = func.__name__
        # Special case; a "name" instance has a "name" attribute we want to use instead.
        if len(args) >= 1 and isinstance(args[0], name):
            funcname = args[0].name
        print '%s took %0.3f s ~ %0.0f min and %0.1f sec' % (funcname, t2-t1, int(t2 - t1)/60, (t2-t1) % 60 )
        return res
    return wrapper

更新:包装器现在默认使用 func.__name__ ,但是如果您在 name 类上使用它(如原始版本中所示)问题),它将使用实例的 name 属性。

我使用了 isinstance 测试来确定 name 属性是否存在,但您可以使用鸭子类型来代替(if hasattr(args) [0], '姓名')); name 变量非常通用,但是当用于任意类方法时,您很可能会得到意想不到的结果。

关于python - 将装饰器与可调用对象一起使用时返回用户定义的函数名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6164291/

相关文章:

python - 使用Python实现Switch : 'null is not callable'

Python 静态方法并不总是可调用的

python - 具有一个热文本嵌入的 Keras LSTM 输入维度

python - 为什么这个点积会产生尺寸误差?

python - 检查网站是否可以通过 www 或不通过 www 访问

python - 如何由 super 用户运行 celery worker ?

python - 为一个完整的模块定义 Python 装饰器

ruby-on-rails - Spree 模块装饰器

python - 装饰器如何在没有正式调用的情况下注册一个函数?

java - 通用可调用