Python语法详解之decorator装饰器

python 是一门优雅的语言,有些使用方法就像魔法一样。装饰器(decorator)就是一种化腐朽性为神奇的技巧。最近一直都在使用 Tornado 框架,一直还是念念不忘 Flask 。Flask 是我最喜欢的 Python 框架,最早被它吸引也是源自它使用装饰器这个语法糖(Syntactic sugar)来做 Router,让代码看上去就感觉甜甜的。

Tornado 中的 Router 略显平淡,怀念 Flask 的味道,于是很好奇的想知道 Flask 是如何使用这个魔法。通过阅读 Flask 的源码,我们也可以为 Tornado 实现了一个装饰器 Router。

当然对于刚接触 Python 的人,也许很容易理解装饰器本质是设计模式中的装饰器模式。可是 Python 通过@一个实现装饰器的语法糖。下面看下Python语法详解之decorator装饰器。

一、定义

装饰器 decorator 或者称为包装器,是对函数的一种包装。

二、作用

它能使函数的功能得到扩充,而同时不用修改函数本身的代码。它能够增加函数执行前、执行后的行为,而不需对调用函数的代码做任何改变。

三、举例

初始化函数

# 函数hello,输出 hello + name 的字符串
def hello(name):
    return 'hello ' + name  

希望实现功能:在每一个调用 hello 函数的时候,将输出的字符串用 <tag>包住

例如:hello john 变成 <tag>hello john<tag>

方法一:自定义wrapper函数

这种方法成功修改了函数 hello 的行为,不过需要修改对 hello的调用。

每一个调用hello 的地方,都要给成调用wrapper,并修改参数列表

def hello(name):
    return 'hello ' + name

def wrapper(tag, func, *arg, **kvargs):
    tag = "<" + tag + ">"
    return tag + func(*arg, **kvargs) + tag

if __name__ == "__main__":
    print(wrapper('p', hello, 'john'))

输出

方法二:自定义decorator函数

为了不改变对 hello的调用。我们需要得到一个新的函数对象,它修改 hello的行为,并用这个对象对 hello赋值。

从而调用 hello的时候,调用的是扩充行为后的 hello

def hello(name):
    return 'hello ' + name
def myDecorator(func, tag):
    def myWrapper(*arg, **kvargs):  # 重新包装func,其参数列表与func一致
        sign = "<" + tag + ">"
        return sign + func(*arg, **kvargs) + sign

    return myWrapper

hello = myDecorator(hello, "div")  # 用新的函数对象修改hello

if __name__ == "__main__":
    print(hello("john")) 

这样,只要hello被myDecorator 赋值一次,以后再调用hello 时,就调用的是包装后的函数

输出

方法三:python的decorator

python 的装饰器所做的事与方式2类似

它通过语法糖使装饰器看起来更清晰、简介,而不用每次都书写方式2中第7行代码 hello = myDecorator(hello, "div")

def setTag(tag):  # 由于此装饰器需要参数,所以要再套一层
    def myDecorator(func):  # 装饰器的核心,接受函数对象做参数,返回包装后的函数对象
        def myWrapper(*arg, **kvargs):  # 包装的具体过程
            sign = "<" + tag + ">"
            return sign + func(*arg, **kvargs) + sign

        return myWrapper

    return myDecorator

@setTag("div")  # 用@标签在定义函数时套上装饰器
def hello(name):
    return 'hello' + name

if __name__ == '__main__':
    print(hello('john'))

本质上,方式2 与 方式3 完成的是同一件事,只不过方式3 比方式2 代码更简洁,方便。

比如,现在要给 hello 函数套上三个标签<body><div><p>

如果用方式2

hello = myDecorator(myDecorator(myDecorator(hello, "body"),"div"),"p")

如果用方式3

@myDecorator("body")
@myDecorator("div")
@myDecorator("p")
def hello(name)
    return 'hello' + name

在多个装饰器嵌套的情况下,python内置的decorator 结构更清晰。

伪代码:

def myDecorator(...):    #定义装饰器,可能带参数
    def decorator(func):    #装饰器核心,以被装饰的函数对象为参数,返回装饰后的函数对象
        def wrapper(*args, **kvargs):    #装饰的过程,参数列表适应不同参数的函数
             ...    #修改函数调用前的行为
             func(*args, **kvargs)    #调用函数
             ...    #修改函数调用后的行为
         return wrapper
     return decorator

@myDecorator(...):    #给函数加上装饰器
def myFunc(...):      #自己定义的功能函数
    ...

知识点:

  • 在python中,当*和**符号出现在函数定义的参数中时,表示任意数目参数收集。*arg表示任意多个无名参数,类型为tuple;**kwargs表示关键字参数,为dict,使用时需将*arg放在**kwargs之前,否则会有“SyntaxError: non-keyword arg after keyword arg”的语法错误
  • 在函数调用时,*会以单个元素的形式解包一个元祖,使其成为独立的参数。
  • 在函数调用时,**会以键/值对的形式解包一个字典,使其成为独立的关键字参数。

到此这篇关于Python语法:decorator装饰器的文章就介绍到这了,更多相关Python decorator装饰器内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 如何实现一个python函数装饰器(Decorator)

    装饰器本质上是一个 Python 函数或类,它可以让其他函数或类在不需要做任何代码修改的前提下增加额外功能,装饰器的返回值也是一个函数/类对象.它经常用于为已有函数/类添加记录日志.计时统计.性能测试等. 首先定义一个倒计时函数,这个函数的功能非常简单,就是把n从当前值减少到0. def countdown(n): while n > 0: print('time' + str(n)) n -= 1 print(countdown.__name__) 程序输出: countdown 1.为函数增

  • Python装饰器decorator用法实例

    本文实例讲述了Python装饰器decorator用法.分享给大家供大家参考.具体分析如下: 1. 闭包(closure) 闭包是Python所支持的一种特性,它让在非global scope定义的函数可以引用其外围空间中的变量,这些外围空间中被引用的变量叫做这个函数的环境变量.环境变量和这个非全局函数一起构成了闭包. 复制代码 代码如下: def outer(x):     y = [1,2,3]     def inner():         print x         print y

  • 深入了解和应用Python 装饰器 @decorator

    Python的装饰器(decorator)是一个很棒的机制,也是熟练运用Python的必杀技之一.装饰器,顾名思义,就是用来装饰的,它装饰的是一个函数,保持被装饰函数的原有功能,再装饰上(添油加醋)一些其它功能,并返回带有新增功能的函数对象,所以装饰器本质上是一个返回函数对象的函数(确切的说,装饰器应该是可调用对象,除了函数,类也可以作为装饰器). 在编程过程中,我们经常遇到这样的场景:登录校验,权限校验,日志记录等,这些功能代码在各个环节都可能需要,但又十分雷同,通过装饰器来抽象.剥离这部分代

  • 分析Python中设计模式之Decorator装饰器模式的要点

    先给出一个四人团对Decorator mode的定义:动态地给一个对象添加一些额外的职责. 再来说说这个模式的好处:认证,权限检查,记日志,检查参数,加锁,等等等等,这些功能和系统业务无关,但又是系统所必须的,说的更明白一点,就是面向方面的编程(AOP). 在Python中Decorator mode可以按照像其它编程语言如C++, Java等的样子来实现,但是Python在应用装饰概念方面的能力上远不止于此,Python提供了一个语法和一个编程特性来加强这方面的功能.Python提供的语法就是

  • python装饰器decorator介绍

    一.装饰器decorator decorator设计模式允许动态地对现有的对象或函数包装以至于修改现有的职责和行为,简单地讲用来动态地扩展现有的功能.其实也就是其他语言中的AOP的概念,将对象或函数的真正功能也其他辅助的功能的分离. 二.Python中的decorator python中的decorator通常为输入一个函数,经过装饰后返回另一个函数.  比较常用的功能一般使用decorator来实现,例如python自带的staticmethod和classmethod. 装饰器有两种形式:

  • 12步入门Python中的decorator装饰器使用方法

    装饰器(decorator)是一种高级Python语法.装饰器可以对一个函数.方法或者类进行加工.在Python中,我们有多种方法对函数和类进行加工,比如在Python闭包中,我们见到函数对象作为某一个函数的返回结果.相对于其它方式,装饰器语法简单,代码可读性高.因此,装饰器在Python项目中有广泛的应用. 装饰器最早在Python 2.5中出现,它最初被用于加工函数和方法这样的可调用对象(callable object,这样的对象定义有call方法).在Python 2.6以及之后的Pyth

  • Python装饰器(decorator)定义与用法详解

    本文实例讲述了Python装饰器(decorator)定义与用法.分享给大家供大家参考,具体如下: 什么是装饰器(decorator) 简单来说,可以把装饰器理解为一个包装函数的函数,它一般将传入的函数或者是类做一定的处理,返回修改之后的对象.所以,我们能够在不修改原函数的基础上,在执行原函数前后执行别的代码.比较常用的场景有日志插入,事务处理等. 装饰器 最简单的函数,返回两个数的和 def calc_add(a, b): return a + b calc_add(1, 2) 但是现在又有新

  • Python语法详解之decorator装饰器

    python 是一门优雅的语言,有些使用方法就像魔法一样.装饰器(decorator)就是一种化腐朽性为神奇的技巧.最近一直都在使用 Tornado 框架,一直还是念念不忘 Flask .Flask 是我最喜欢的 Python 框架,最早被它吸引也是源自它使用装饰器这个语法糖(Syntactic sugar)来做 Router,让代码看上去就感觉甜甜的. Tornado 中的 Router 略显平淡,怀念 Flask 的味道,于是很好奇的想知道 Flask 是如何使用这个魔法.通过阅读 Flas

  • 详解C++泛型装饰器

    目录 c++ 装饰器 对输出的解释 总结 c++ 装饰器 本文简单写了个 c++ 装饰器,主要使用的是c++ lamda 表达式,结合完美转发技巧,在一定程度上提升性能 #define FieldSetter(name, type, field) \ type field; \ name() {} \ name(const type& field): field(field) { \ cout << "[左值 " << field << &q

  • 详解 Python中LEGB和闭包及装饰器

    详解 Python中LEGB和闭包及装饰器 LEGB L>E>G?B L:local函数内部作用域 E:enclosing函数内部与内嵌函数之间 G:global全局作用域 B:build-in内置作用域 python 闭包 1.Closure:内部函数中对enclosing作用域变量的引用 2.函数实质与属性 函数是一个对象 函数执行完成后内部变量回收 函数属性 函数返回值 passline = 60 def func(val): if val >= passline: print (

  • python中的迭代器,生成器与装饰器详解

    目录 迭代器 生成器 装饰器 总结 迭代器 每一个可迭代类内部都要实现__iter__()方法,返回一个迭代类对象,迭代类对象则定义了这个可迭代类如何迭代. for循环调用list本质上是是调用了list的迭代器进行迭代. # 对list进行for循环本质上是调用了list的迭代器 list = [1,2,3,4] # for 循环调用 for elem in list: print(elem) # 迭代器调用 list_iter = list.__iter__() while True: tr

  • Python高级特性之闭包与装饰器实例详解

    本文实例讲述了Python高级特性之闭包与装饰器.分享给大家供大家参考,具体如下: 闭包 1.函数参数: (1)函数名存放的是函数的地址 (2)函数名()存放的是函数内的代码 (3)函数名只是函数代码空间的引用,当函数名赋值给一个对象的时候,就是引用传递 def func01(): print("func01 is show") test = func01 print(func01) print(test) test() 结果: 2.闭包: (1)内层函数可以访问外层函数变量 (2)闭

  • 详解利用上下文管理器扩展Python计时器

    目录 一个 Python 定时器上下文管理器 了解 Python 中的上下文管理器 理解并使用 contextlib 创建 Python 计时器上下文管理器 使用 Python 定时器上下文管理器 写在最后 上文中,我们一起学习了手把手教你实现一个 Python 计时器.本文中,云朵君将和大家一起了解什么是上下文管理器 和 Python 的 with 语句,以及如何完成自定义.然后扩展 Timer 以便它也可以用作上下文管理器.最后,使用 Timer 作为上下文管理器如何简化我们自己的代码. 上

  • Python Decorator装饰器的创建方法及常用场景分析

    目录 前言 一.创建方式 二.常用场景 前言 1.装饰器本质是一个语法糖,是对被装饰方法或类进行的功能扩充,是一种面向切面的实现方法2.装饰器可以分成方法装饰器和类装饰器,他们的区别是一个是用函数实现的装饰器,一个是用类实现的装饰器,他们也都能在方法和类上进行装饰3.类装饰器看起来结构更加清晰,因此下面的代码实现的装饰器全是类装饰器 一.创建方式 1.创建“装饰方法”的类装饰器 from functools import wraps # 装饰器类 class MyDecorator(object

  • 对Python 3.5拼接列表的新语法详解

    在Python 3.5之前的版本,拼接列表可以有这两种方法: 1.列表相加 list1 = [1,2,3] list2 = [4,5,6] result = list1 + list2 结果为一个新的列表 2.在原来列表上扩展 list1 = [1,2,3] list2 = [4,5,6] list1.extend(list2) list1扩展后,结果为[1,2,3,4,5,6] 3.新语法 如果列表是由range()生成: list1 = [1,2,3] list2 = range(4,6)

随机推荐