【问题标题】:decorating decorators in python在 python 中装饰装饰器
【发布时间】:2014-09-24 06:55:12
【问题描述】:

我无法理解装饰器在 Python (2.7.2) 中的工作原理。我有以下代码:

def verbose(function):
    print 'i am verbose and func is ' + function.__name__
    def wrapper2(func):
        print 'func is ' + repr(func)
        result = function(func)
        return result
    return wrapper2

@verbose
def more(function):
    print 'i am more and func is ' + function.__name__
    def wrapper1(*args, **kwargs):
        print 'args' + repr(args)
        result = function(*args)
        return result
    return wrapper1

@more
def hello(*args):
    print(sum(args))

当我跑步时:

>>> hello(1,2,3)

这是我得到的:

i am verbose and func is more
func is <function hello at 0x1015338c0>
i am more and func is hello    
args(1, 2, 3)
6

我无法想象生成此输出的调用顺序。我认为下面的调用仍然会产生相同的输出,我很想了解装饰装饰器在这个特定示例中是如何工作的。

>>> verbose(more)(hello)(1,2,3)
i am verbose and func is more
func is <function hello at 0x101533d70>
i am more and func is hello
args(1, 2, 3)
6

【问题讨论】:

  • 您的代码会生成 NameError,因为您尝试在定义之前使用装饰器。你真的在more 上面定义了verbose 吗?此外,即使您这样做,您显示的某些输出也会在定义 hello 时生成,而在定义 more 时会生成一些输出,而不是在调用 hello 时生成。您的示例中的 python&gt;&gt; 提示符是什么?
  • 修复了名称错误。是的,当我定义more 和定义hello 方法时会生成一些输出。我只是在这里粘贴以确保两种调用方式生成相同的输出。

标签: python python-decorators


【解决方案1】:

您减少到verbose(more)(hello)(1,2,3) 是正确的。但是,这些电话发生在不同的时间。请记住:

@deco
def func():
    # whatever

和这个是一样的:

def func():
    # whatever
func = deco(func)

所以当你定义more 时,verbose 会被调用。当您定义hello 时,会调用more(装饰版本)。您的代码相当于:

def verbose(function):
    print 'i am verbose and func is ' + function.__name__
    def wrapper2(func):
        print 'func is ' + repr(func)
        result = function(func)
        return result
    return wrapper2

def more(function):
    print 'i am more and func is ' + function.__name__
    def wrapper1(*args, **kwargs):
        print 'args' + repr(args)
        result = function(*args)
        return result
    return wrapper1
more = verbose(more)

def hello(*args):
    print(sum(args))
hello = more(hello)

这应该清楚哪些函数调用发生在什么时候。请注意,当您调用 hello(1, 2, 3) 时,moreverbose 都不会被调用。装饰器在被装饰函数定义时被调用,而不是在被调用时被调用。在调用时,调用的是装饰器的返回值(即您的示例中的函数 wrapper1wrapper2)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-07
    • 2014-01-23
    • 2017-08-20
    • 2021-05-20
    • 2020-02-10
    • 2011-09-03
    • 2015-11-18
    相关资源
    最近更新 更多