【问题标题】:Why doesn't this python decorator print the value from the original function?为什么这个 python 装饰器不打印原始函数的值?
【发布时间】:2017-04-21 21:23:07
【问题描述】:

我正在尝试学习 Python 中的装饰器,每次我想我都会遇到这样的问题。我不知道为什么来自my_func 的打印语句不会显示,而是返回“无”。如果我在包装器return (func, wrapper) 的返回语句中包含func,我会收到一条错误消息,指出元组对象不可调用。这个例子有什么问题?

def my_dec(func):
    def wrapper():
        decoration = "decorated"
        print(decoration)
    return wrapper

@my_dec
def my_func():
    a = "Original"
    print (a)

print(my_func())

【问题讨论】:

  • 您可以通过包含预期和实际输出来改进您的问题。

标签: python function decorator


【解决方案1】:

你永远不会在你的wrapper 中调用包装好的func。添加通话,例如:

def my_dec(func):
    def wrapper():
        decoration = "decorated"
        print(decoration)
        # Call the decorated function and return what it returns
        return func()

    return wrapper

@my_dec
def my_func():
    a = "Original"
    print (a)

print(my_func())

现在会产生(因为func()implicitly returns None):

decorated
Original
None

如果我在包装器return func, wrapper 的返回语句中包含func,我会收到一条错误消息,指出元组对象不可调用。

这个错误一定是你做了类似的事情:

def my_dec(func):
    def wrapper():
        decoration = "decorated"
        print(decoration)

    # Now `my_dec` returns a tuple instead of a function
    return func, wrapper

记得装饰is (roughly) equivalent to just doing:

def my_func():
    ...

my_func = my_dec(my_func)

您的 my_dec() 装饰器现在返回元组 (func, wrapper) 而不是包装函数,因此当您尝试调用 my_func() 时,实际上是在尝试“调用”已分配给 my_func 的元组.

作为一个很好的衡量标准,您应该学习如何使用functools.wraps,这是一个调用update_wrapper() 的便捷函数,它将包装器 函数更新为看起来像func

from functools import wraps

def my_dec(func):
    @wraps(func)
    def wrapper():
        decoration = "decorated"
        print(decoration)
        return func()

    return wrapper

没有它你会得到:

In [4]: print(my_func.__name__)
wrapper

并带有包装:

In [9]: print(my_func.__name__)
my_func

它还会复制其他有用的属性,例如__doc__

【讨论】:

  • 这对我来说很有意义。非常感谢。我现在也将探索 functools.wraps。
猜你喜欢
  • 2021-05-10
  • 2015-08-18
  • 2018-03-27
  • 2018-09-12
  • 1970-01-01
  • 2015-11-21
  • 2016-11-01
  • 1970-01-01
  • 2016-11-25
相关资源
最近更新 更多