【问题标题】:Why are decorator functions designed in the way they are? [closed]为什么装饰器函数按它们的方式设计? [关闭]
【发布时间】:2020-10-14 01:53:55
【问题描述】:

困扰了我很久。为什么装饰器函数要这样设计,在我看来它们过于复杂。让我们以这样的例子为例:

def dec(f):
    def wrapper(a, b):
        print('Hello')
        f(a, b)
        print('Bey')
    return wrapper

@dec
def func(a, b):
    print(a)
    print(b)

为什么要在装饰器中添加一个函数,将功能包装在dec 函数中?我知道引擎就是这样工作的,但为什么不做一些简单的事情呢。像这样:

def dec(f, a, b):
    print('Hello')
    f(a, b)
    print('Bey')

@dec
def func(a, b):
    print(a)
    print(b)

稍微改变一下引擎,让@运算符将函数名和参数作为参数传递给dec函数。使用第一个结构有什么好处,因为我们可以用同样的方式轻松装饰第二个结构?

如果您能给我一个示例,说明第二个示例无法解决问题 - 请分享您的知识。

票证已关闭,因为一些用户要求更清楚地了解问题,以帮助我解决问题。我必须说没有问题需要解决。我提出这个问题是为了收集有关装饰器设计方式为何如此的信息。这将帮助我了解我可以在未来使用现有的装饰器模型解决哪些其他问题。

很抱歉,如果您对这个问题有任何不清楚的地方。我认为听听有经验的 Python 用户对此有何看法并与不了解装饰函数中包装器用途的任何人分享他们的知识会很有趣。

【问题讨论】:

  • 因为装饰器语法,@ 出现在 装饰器的想法之后,装饰器是一个返回可调用对象的可调用对象,它修改传入的可调用对象的某些操作。 @dec def func 只是 def func()...; func = deco(func) 的语法糖。基本上,您是在问“为什么装饰者是装饰者”
  • 无论如何,你没有定义一个函数。装饰器可以做其他事情,然后只需 return f 您的想法会强制它充当包装器。
  • @IgorDragushhak 再次,因为装饰器只是一个返回可调用对象的可调用对象。它没有 来定义包装器。你的想法会迫使它这样做。同样,语法糖是这个想法之后出现的。您必须重新编写 2003 年之前存在的所有装饰器才能像您提供的那样工作。此外,它如何与非功能装饰器(基于类的装饰器)一起使用?
  • @dec(a, b) 调用dec(f, a, b) 而不是dec(a, b)(f) 会有很大的优势。例如,将@dec@dec() 统一起来,可以更轻松地将可选参数添加到以前没有使用它们的装饰器中,并避免函数与另一个参数混淆的情况。我一直希望 Python 的装饰器语法是这样设计的。
  • 这个问题提出的语义有很大的局限性。特别是,不再支持带参数的装饰器(如@dec(a, b)),不再支持创建非函数对象的装饰器如@property

标签: python decorator


【解决方案1】:

装饰器应该返回一个函数而不是函数的结果。在您的第一个示例中,它返回一个函数......在第二个示例中,它返回您的函数 f 返回的任何内容。 - julien

  1. 为什么第二个样本不起作用?

    因为您在返回时调用函数,所以您没有返回函数。

  2. 如果我们使用嵌套函数,为什么 args,kwargs 会“神奇地”出现?

    它们不会神奇地出现,我们是在声明它们,如下所示:

    def deco(*args, **kwargs):
    

    这些是通用的,将匹配任何函数签名(参数列表)。你不必叫他们argskwargs,这只是一个约定,你可以叫他们sharontracy

  3. 我该怎么做才能使第二个样本工作?当然,除了嵌套另一个函数。

    嗯,你没有说你期望第二个样本做什么。但我想把它变成一个装饰器:

    def func(f):
        return f
    

    但这并没有多大作用!

顺便说一句,覆盖现有的 Python 内置函数 (sum) 通常是个坏主意——你必须有一个很好的理由。 - cdarke

Source

【讨论】:

    猜你喜欢
    • 2010-09-21
    • 2023-04-06
    • 2014-02-20
    • 1970-01-01
    • 2014-04-09
    • 2018-01-02
    • 2019-03-06
    • 2017-10-24
    相关资源
    最近更新 更多