python-3.x - 了解这个 Python 装饰器是如何工作的

标签 python-3.x wrapper python-decorators

我一直在研究如何创建自己的装饰器,并给出了以下示例:

def counter(func):
  def wrapper(*args, **kwargs):
    wrapper.count += 1
    # Call the function being decorated and return the result
    return wrapper.count
  wrapper.count = 0
  # Return the new decorated function
  return wrapper

# Decorate foo() with the counter() decorator
@counter
def foo():
  print('calling foo()')
  
foo()
foo()

print('foo() was called {} times.'.format(foo.count))
我不明白那段代码的逻辑。
  • 如何引用自身内部的函数( wrapper.count )?
  • 在定义包装器之前,包装器的方法计数如何?
  • 每次调用 foo() 时不应该执行 line wrapper.count = 0 吗?
  • 最佳答案

    1. How can I reference a function inside itself (wrapper.count)?

    函数体只有在你调用它时才会执行。到那时,该功能已经定义,所以这就是使之成为可能的原因。以下不会给您任何错误,除非您调用它:
    >>> def foo():
    ...     non_existing_function()
    ...
    
    每当你进入 foo 的正文, foo已经定义好了,所以你可以引用它。这也是使递归调用成为可能的原因。
    1. How wrapper has the method count before wrapper is defined?

    问题也可能是“如何在 wrapper.count 初始化之前增加它?”
    但同样,我们可以用同样的方式回答这个问题:因为函数体在我们调用它们之前不会被执行,wrapper.countwrapper.count += 1 之前初始化为 0 .
    1. Shouldn't the line wrapper.count = 0 be executed everytime I call foo()?

    让我们看看发生了什么。你写:
    @counter
    def foo():
      print('calling foo()')
    
    这只是一个语法糖:
    foo = counter(foo)
    
    现在,我们调用counter功能与 foo作为论据。什么counter做?
    def counter(func):
      def wrapper(*args, **kwargs):
        wrapper.count += 1
        # Call the function being decorated and return the result
        return wrapper.count
      wrapper.count = 0
      # Return the new decorated function
      return wrapper
    
    在人类语言中,
  • 定义一个名为 wrapper 的函数它采用未知数量的位置和关键字参数
  • 分配 0作为一个名为 count 的属性对于 wrapper功能
  • 返回 wrapper给来电者

  • 当我们将结果分配回 foo函数,我们实际上分配了wrapperfoo .所以当我们调用 foo ,我们实际上是在调用 wrapper .行wrapper.count = 0wrapper 之外函数,所以它不会在我们每次调用 foo 时运行.
    最后,我强烈建议您观看精彩PyCon talk by Reuven M. Lerner关于装饰师。
    编辑:我没有阅读包装器的正文,这实际上证明您并不需要知道包装器内的内容。我的解释仍然是正确的。但是,正如 @Mark Tolonen's answer 中所建议的那样,您的包装器可能应该返回 func(*args,**kwargs) 不是 wrapper.count

    关于python-3.x - 了解这个 Python 装饰器是如何工作的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62576512/

    相关文章:

    python - 我应该在我编写的每个 Python 脚本中包含这个样板代码吗?

    android - gradle没有更新我不知道问题我可以得到帮助

    python - 装饰器的文档字符串放在哪里

    python - Python 3 continue 循环语句在 Odoo 13 的计算方法中是否存在问题?

    python - 如何使用python3分割字符串

    C# 包装器类和来自 C++ 的 dllimport

    height - 改变容器高度

    python - python 如何知道何时传入 `self` ?

    python - 应用于方法的可调用对象装饰器不会在输入中获取自参数

    python - 如何在c内部调用静态pyobject类型的c函数