【问题标题】:Where does a python decorator get the arguments from the decorated functionpython 装饰器在哪里从装饰函数中获取参数
【发布时间】:2018-01-21 01:47:57
【问题描述】:

我有这个代码:

def foo(bar):
    def test(some_string):
        return 'Decorator test: '+bar(some_string)
    return test


def main():
    print(bar('test1'))


@foo
def bar(some_string):
    return some_string[:3]

我知道调用bar('test1) 基本上是调用foo(bar('test1')),但是当我尝试在其他函数之前在foo 中打印some_string 时,我得到some_string is not defined

def foo(bar):
    print(some_string)
    def test(some_string):
        return 'Decorator test: '+bar(some_string)
    return test
  1. test 怎么知道some_stringfoo 不知道?
  2. 为什么我必须返回test 才能让装饰器工作?直接返回 Decorator test: '+bar(some_string) 不起作用,因为 some_string 未定义。

【问题讨论】:

  • 不。这是foo(bar)('test1')

标签: python decorator python-decorators


【解决方案1】:

我知道调用bar('test1)基本上就是调用foo(bar('test1'))

不,不是,你的理解不正确。它基本上是在调用

foo(bar)('test')

@foo 装饰器语法告诉 Python 调用 foo(),传入由 bar 命名的函数对象(并将结果分配回名称 bar)。

foo() 装饰器返回了一个新的函数对象:

def test(some_string):
    # ...
return test

所以foo(bar) 的结果是名为test 的函数对象(foo() 装饰器中的本地名称)。 foo(bar)('test') 因此称为test('test')

如果您想打印传递给test(..) 的参数,请在该函数中执行

def foo(bar):
    def test(some_string):
        print(some_string)
        return 'Decorator test: '+bar(some_string)
    return test

【讨论】:

    【解决方案2】:

    我知道调用bar('test1)基本上就是调用foo(bar('test1'))

    不,这是不正确的。

    调用bar('test1')相当于

    bar = foo(bar)
    bar('test1')
    

    为什么我必须返回test 才能让装饰器工作?直接返回 Decorator test: '+bar(some_string) doesn't work as some_string is not defined.

    当你这样做时

    @decorator
    def func():
        pass
    

    Python 将其翻译成

    def func():
        pass
    
    func = decorator(func)
    

    如您所见,Python 期望 decorator 返回一个 new 函数。这就是为什么您必须从foo 返回test 以使bar 正常工作。否则,None 分配给bar

    >>> def foo(bar):
        def test(some_string):
            return 'Decorator test: '+bar(some_string)
    
    
    >>> @foo
    def bar(some_string):
        return some_string[:3]
    
    >>> bar()
    Traceback (most recent call last):
      File "<pyshell#6>", line 1, in <module>
        bar()
    TypeError: 'NoneType' object is not callable
    

    test 如何知道 some_string 而 foo 不知道?

    仅仅是因为在达到test 之前不会创建some_stringsome_stringtest的参数,所以只存在于test的范围内。否则,不存在名称 some_string,因此如果您尝试访问它,您将得到一个 NameError - 包括在 foo 内部。

    如果你想printsome_string 的值,在test 里面做:

    def foo(bar):
        def test(some_string):
            print(some_string)
            return 'Decorator test: '+bar(some_string)
        return test
    

    【讨论】:

      猜你喜欢
      • 2014-07-21
      • 2013-06-03
      • 2010-11-03
      • 2021-11-21
      • 2016-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多