【问题标题】:Python decorator accessing the wrong functionPython 装饰器访问错误的函数
【发布时间】:2017-06-06 11:04:19
【问题描述】:

我的理解:

根据我对装饰器的理解,下面的代码

def myDecorator(func):
   ...

@myDecorator
def myFunc()

等价于

myFunc = myDecorator(myFunc)

我的实验

所以我用下面的代码玩弄这个概念

def myDecorator(func):
        func()

@myDecorator
def myFunc():
    print("MyFunc is run")

@myDecorator
def myFunc2():
    print("MyFunc2 is run")

myFunc

输出是

MyFunc is run
MyFunc2 is run

我的问题

会发生什么?为什么要打印MyFunc2 is run 行? myFunc不等于myFunc = myDecorator(myFunc)吗?如果是这种情况,为什么要运行myFunc2 语句?

【问题讨论】:

  • 为什么不呢?函数也是对象,你将MyFunc2() 传递给装饰器函数,它以func 接收它。然后你打电话给func()
  • You're last line with myFunc 不运行该功能。您缺少括号。
  • @Matthias 在这种情况下它不需要括号,因为 myDecorator 已经调用了函数
  • 这就是我想要解释的。 myFunc 行不会导致任何操作,因此导致打印的调用在另一个地方完成。
  • @MartijnPieters 不应该只在我添加另一行 myFunc2 时触发 myFunc2(我刚刚将代码从 MyFunc2 编辑到 myFunc2,错字)?为什么我只发出声明myFunc时会调用它?

标签: python python-3.x python-decorators


【解决方案1】:

您正在将一个函数对象传递给myDecorator() 函数。该函数接收函数对象作为func 参数。然后,您使用func()调用该函数。

你是对的,函数对象上的@myDecorator 会导致调用装饰器,并传入函数对象。但你似乎对什么时候发生感到困惑。它发生在 Python 执行 def 语句的那一刻:

>>> def myDecorator(func):
...     func()
...
>>> @myDecorator
... def foo():
...     print('The foo() function is called')
...
The foo() function is called

请注意,因为myDecorator() 没有return 语句,所以foo 现在绑定到None

>>> foo is None
True

您的最后一行 myFunc 只是引用 None 对象。你没有调用它,所以 那个 表达式不会导致打印任何内容。你不能调用它,因为None 是不可调用的。

【讨论】:

  • 我明白你的意思。
【解决方案2】:

为了完整起见 - “通用”正确的装饰器返回一个新的函数对象,然后替换它声明的范围内的原始函数:

def myDecorator(func):
    def wrapper(*args, **kwargs):
        """Calls original function with whatever parameters 
        and returns its return value.
        """
        print("Running decorator code")
        return func(*ars, **kwargs)
    # Returns the newly created 'wrapper' function
    # that will replace the original "func"
    return wrapper

@myDecorator
def myFunc():
    print("MyFunc is run")

@myDecorator
def myFunc2():
    print("MyFunc2 is run")

myFunc()

【讨论】:

    猜你喜欢
    • 2018-01-28
    • 2011-06-25
    • 1970-01-01
    • 2012-04-21
    • 2011-09-22
    • 2020-05-02
    • 2013-06-08
    • 1970-01-01
    • 2019-06-14
    相关资源
    最近更新 更多