繁体   English   中英

Python 装饰器究竟是如何工作的?

[英]How exactly works Python decorator?

我绝对是 Python 新手(我来自 Java 和 C#)

我正在研究装饰器主题。 所以我有以下例子:

# DECORATOR:
def my_decorator(func):
  def wrap_func():
    print('**************')
    func()
    print('**************')
  return wrap_func


@my_decorator
def hello():
  print('Hello World')

hello()

在我看来,这就是逻辑(但我不确定这一点:

我正在定义一个以另一个函数作为参数的my_decorator函数。 这个my_decorator函数将作为参数传递的函数包装到一个wrap_func()函数中,该函数执行作为参数传递的函数。 另外这个wrap_func()函数可以在作为参数传递的函数执行前后执行一些额外的逻辑(它是装饰原始函数。

要对解释器说特定函数必须使用装饰器,我必须在函数定义之前使用语法@decorator_name

所以在我的例子中:当我执行hello()调用时:Python 知道hello()函数必须由my_decorator装饰器装饰,所以它不是直接执行hello()函数而是执行my_decorator()函数传递hello ()引用作为参数。 因此它可以在hello()调用之前和之后添加额外的逻辑。

这个推理是正确的还是我错过了什么?

我还有一个疑问:为什么装饰器函数返回包装我们装饰逻辑的函数?

装饰器只是函数调用的语法糖。

装修

@my_decorator
def hello():
    print('Hello world')

相当于

def hello():
    print('Hello world')

hello = my_decorator(hello)

所以在这种情况下,使用装饰器语法与直接定义以下函数是一样的:

def hello():
    print('**************')
    print('Hello world')
    print('**************')

装饰器创建一个函数,调用print('**************') ,然后调用原始函数,然后调用print('**************')再次。

如果你只打算装饰一次函数,这显然只是很多不必要的样板。 但是,如果您要装饰多个函数,则抽象是值得的:

# DECORATOR:
def my_decorator(func):
  def wrap_func():
    print('**************')
    func()
    print('**************')
  return wrap_func


@my_decorator
def hello():
  print('Hello World')

@my_decorator
def how_are_you():
  print("How are you doing?")

@my_decorator
def goodbye():
  print('Goodbye, world')

对比

def hello():
    print('**************')
    print('Hello world')
    print('**************')

def how_are_your():
    print('**************')
    print('How are you doing')
    print('**************')

def good_bye():
    print('**************')
    print('Goodbye world')
    print('**************')

特别是如果您后来决定用==============代替**************包装每个输出。

装饰器只是一种语法糖。 这个:

@decorator
def func():
    pass

相当于:

def func():
    pass

func = decorator(func)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM