美文网首页
Python函数装饰器(decorator)

Python函数装饰器(decorator)

作者: DongGuangqing | 来源:发表于2020-01-31 22:45 被阅读0次

装饰器(decorator)在你希望不修改函数本身的前提下扩展函数的功能时非常有用。decorator就像一个wrapper一样,在函数执行之前或者之后修改该函数的行为,而无需修改函数本身的代码,这也是装饰器名称的来由。

0. Python中@的用法

在介绍装饰器之前,先介绍一下Python中@的用法。
@是一个装饰器,针对函数,起调用传参的作用。@function作为一个装饰器,用来修饰紧跟着的函数(可以是另一个装饰器,也可以是函数定义)。

def funA(desA):
    print("It's funA")

@funA
def funC():
    print("It's funC")

输出结果为:

It's funA

这是因为:@funA 修饰函数定义def funC(),将funC()赋值给funA()的形参。执行的时候由上而下,先定义funA,然后运行funA(funC())。此时desA=funC(),然后funA()输出‘It's funA'

1. 原始状态装饰器

def get_text(name):
   return "lorem ipsum, {0} dolor sit amet".format(name)

def p_decorate(func):
   def func_wrapper(name):
       return "<p>{0}</p>".format(func(name))
   return func_wrapper

# 通过get_text=p_decorate(get_text)的方式覆盖了get_text从而形成了有新功能的同名函数
get_text = p_decorate(get_text)
print get_text("John")

本质上,decorator就是一个返回函数的高阶函数。在上面的示例中,p_decorate是一个函数装饰器,通过get_text=p_decorate(get_text)的方式覆盖了get_text,从而形成了有新功能的同名函数。运行程序会输出:

<p>Outputs lorem ipsum, John dolor sit amet</p>

2. python 修饰符语法糖

def p_decorate(func):
   def func_wrapper(name):
       return "<p>{0}</p>".format(func(name))
   return func_wrapper

@p_decorate
def get_text(name):
   return "lorem ipsum, {0} dolor sit amet".format(name)

print get_text("John")

使用Python的@语法,把decorator置于函数的定义处,相当于执行get_text=p_decorate(get_text)。运行上面的程序,同样会输出:

<p>Outputs lorem ipsum, John dolor sit amet</p>

3. class method装饰器

python中类的方法是一个首参数为self指针的函数。我们可以和普通函数一样去做修饰,但是需要注意的是必须在wrapper函数中考虑self指针参数。

def p_decorate(func):
   def func_wrapper(self):
       return "<p>{0}</p>".format(func(self))
   return func_wrapper

class Person(object):
    def __init__(self):
        self.name = "John"
        self.family = "Doe"

    @p_decorate
    def get_fullname(self):
        return self.name+" "+self.family

my_person = Person()
print my_person.get_fullname()

一个更好的方案是调整代码使得我们的装饰器对于函数或者method同样适用。这可以通过通过将args和*kwargs放到wrapper函数中作为参数来实现,这样可以接受任意个数的参数或者keyword型参数。

def p_decorate(func):
   def func_wrapper(*args, **kwargs):
       return "<p>{0}</p>".format(func(*args, **kwargs))
   return func_wrapper

class Person(object):
    def __init__(self):
        self.name = "John"
        self.family = "Doe"

    @p_decorate
    def get_fullname(self):
        return self.name+" "+self.family

my_person = Person()
print my_person.get_fullname()

4. 向decorator传入参数

from functools import wraps

def tags(tag_name):
    def tags_decorator(func):
        # functools模块包含了wraps函数。wraps也是一个decorator,但是仅仅用于更新wrapping function(func_wrapper)的属性为原始函数的属性(get_text)
        @wraps(func)
        def func_wrapper(name):
            return "<{0}>{1}</{0}>".format(tag_name, func(name))
        return func_wrapper
    return tags_decorator

@tags("p")
def get_text(name):
    return "Hello "+name

print get_text("John")

其中,functools模块的wraps函数也是一个decorator,但是仅仅用于更新wrapping function(func_wrapper)的属性为原始函数的属性(get_text)。

@tags("p") 相当于调用tags(tag_name="p"), 然后返回一个装饰器tags_decorator。然后相当于运行 get_text = tags_decorator(func= get_text)

运行后会输出:

Outputs <p>Hello John</p>

更多干货,欢迎关注个人博客:http://mochi.website/

相关文章

  • Python中的Decorator装饰器

    Decorator 装饰器 理解decorator(装饰器)的关键, 在于理解在python中函数是第一公民, 并...

  • python Decorator (装饰器)

    Python 装饰器Python 装饰器 Decorator 使用kotlin的时候发现有个函数很好玩 measu...

  • Python装饰器

    Python装饰器 装饰器的本质是什么? 装饰器等价于高阶函数,形如myfunc=decorator(myfunc...

  • JavaScript装饰器 Decorator

    前言 许多面向对象都有decorator(装饰器)函数,比如python中也可以用decorator函数来强化代码...

  • decorator 装饰器

    许多面向对象都有decorator(装饰器)函数,比如python中也可以用decorator函数来强化代码,de...

  • python常用的装饰器

    Python中有很多装饰器(decorator),可以减少冗余代码。Decorator本质上也是函数,只是它的参数...

  • PYTHON部分基础D4

    Decorator装饰器 装饰器自己可以有参数 内置函数 文件读写 Python3的继承机制 成员保护和访问限制 ...

  • python装饰器的wraps作用

    Python装饰器(decorator)在实现的时候,被装饰后的函数其实已经是另外一个函数了(函数名等函数属性会发...

  • Python中@property的使用讲解

    装饰器(decorator)可以给函数动态加上功能,对于类的方法,装饰器一样起作用。Python内置的@prope...

  • python中的方法和装饰器

    [TOC] 装饰器 python中的装饰器(decorator)是在pep 318中被首次引入,它的本质是一个函数...

网友评论

      本文标题:Python函数装饰器(decorator)

      本文链接:https://www.haomeiwen.com/subject/gptvhctx.html