【问题标题】:How instance attributes are passed to the decorator inner function?实例属性如何传递给装饰器内部函数?
【发布时间】:2021-12-09 10:07:34
【问题描述】:

我最近研究了装饰器如何在 python 中工作,并找到了一个将装饰器与嵌套函数集成的示例。 代码在这里:

def integer_check(method):
    def inner(ref):
        if not isinstance(ref._val1, int) or not isinstance(ref._val2, int):
            raise TypeError('val1 and val2 must be integers')
        else:
            return method(ref)
    return inner


class NumericalOps(object):
    def __init__(self, val1, val2):
        self._val1 = val1
        self._val2 = val2

    @integer_check
    def multiply_together(self):
        return self._val1 * self._val2

    def power(self, exponent):
        return self.multiply_together() ** exponent

y = NumericalOps(1, 2)

print(y.multiply_together())
print(y.power(3))

我的问题是内部函数参数(“ref”)如何访问实例属性(ref._val1 和 ref._val2)? 似乎 ref 等于实例,但我不知道它是如何发生的。

【问题讨论】:

    标签: python python-decorators nested-function


    【解决方案1】:

    让我们首先回顾一下装饰器是如何工作的:

    用装饰器@integer_check装饰方法multiply_together相当于添加了这行:multiply_together = integer_check(multiply_together),根据multiply_together的定义,这相当于multiply_together = inner

    现在,当您调用方法multiply_together 时,由于这是一个实例方法,Python 会隐式添加用于调用该方法的类实例作为它的第一个(在这种情况下是唯一的)参数。但是multiply_togethet 实际上是inner,所以实际上inner 是用类实例作为参数调用的。这个实例被映射到参数ref,并且通过这个参数函数可以访问所需的实例属性。

    【讨论】:

    • 感谢您的完整回答
    【解决方案2】:

    前段时间我发现的关于self 参数的一种解释是:

    y.multiply_together()
    

    大致相同

    NumericalOps.multiply_together(y)
    

    所以现在你使用了那个装饰器,它返回函数inner,它需要ref 参数,所以我看到大致是这样发生的(在较低级别上):

    NumericalOps.inner(y)
    

    因为inner“替代”multiply_together同时还添加了额外的功能

    【讨论】:

      【解决方案3】:

      inner替换原来的函数作为类属性的值。

      @integer_check
      def multiply_together(self):
          return self._val1 * self._val2
      
      # def multiply_together(self):
      #     ...
      #
      # multiply_together = integer_check(multiply_together)
      

      首先定义一个函数并将其绑定到名称multiply_together。然后将该函数作为参数传递给integer_check,然后integer_check 的返回值绑定到名称multiply_together。原始函数现在仅由名称 ref 引用,该名称是 inner/multiply_together 的本地名称。

      inner 的定义意味着integer_check 只能应用于第一个参数将具有名为_val1_val2 的属性的函数。

      【讨论】:

        猜你喜欢
        • 2017-11-12
        • 1970-01-01
        • 2021-08-20
        • 2021-11-15
        • 2018-03-23
        • 2021-11-21
        • 2016-02-14
        • 1970-01-01
        相关资源
        最近更新 更多