通俗易懂了解Python装饰器原理

作用

装饰器可以用于用于装饰一个函数或方法,使得在不修改原函数、方法代码的前提下,为方法添加前置或后置操作;

例如突然想要计算一下各个函数的执行时间,又不希望在每一个函数中添加tim.time()来计算执行时间

用法

装饰器的写法网上很多,但是我觉得还是尽量先理解,再知道怎么写会比较好,所以会先说如何理解,在后面重写用法

实现

了解装饰器是如何实现的,远比会写装饰器更重要,简单的说装饰器就是接收一个函数对象,然后先执行前置操作,再执行函数,再执行后置操作;

这么说可能有些抽象,或者举一个不那么恰当的比较贴近生活的例子;

假设你有一台像这样的小风扇:

这台风扇可以充电,有一个开关,打开之后扇叶会旋转,开始工作,当然你也可以插着电打开开关,也可以充好电之后带走,在其他地方打开开关

如果把这个风扇置于一切皆是对象的Python中,风扇就是一个对象,他实现的功能就是出风:

def fengshan():
  return '出风'

为了更好和例子结合,我们用pinyin命名

现在我们实现了一个fengshan函数,返回吹风

如果你稍微有点基础,你就能知道如何调用这个方法

def fengshan():
  return '出风'
print(fengshan())

不要觉得这很基础很墨迹,如果需要理解装饰器,你必须知道,调用函数的方式是函数名称加上括号fengshan()
而这个基础中的基础中的括号()就是执行函数的开关,如果我们不加括号

def fengshan():
  return '出风'
print(fengshan)

返回的将是一个函数对象(例子中的风扇本身)

<function fengshan at 0x7f8e7c4a6950>

这里的意思是 一个叫fengshan的funciont,地址在0x7f8e7c4a6950

那现在我们就可以把风扇带走,在其他地方使用

def fengshan():
  return '出风'

func = fengshan
print(fengshan)
print(func)

返回

<function fengshan at 0x7f570eaf3950>
<function fengshan at 0x7f570eaf3950>

这说明func和fengshan是等价的,他们在同一块内存中,所以当我们执行func() 也等价于执行fengshan

def fengshan():
  return '出风'

func = fengshan
print('下面是执行fengshan')
print(fengshan())
print('下面是执行func')
print(func())

返回

下面是执行fengshan

出风

下面是执行func

出风

理解到这里之后你也就能理解装饰器的实现了,让我们再看一个例子

def fengshan():
  return '出风'
def wrapper(func):
  return func
print(fengshan)
print(wrapper(fengshan))

这个例子中我们除了保留刚刚一直在用的fengshan函数之外,又定义了一个wrapper

因为python中一切皆是对象,函数也是对象,而函数的入参也可以接收对象,所以函数对象可以作为参数传递给另一个函数wrapper

这个wrapper中什么都没有做,只是返回了接收的func对象,我们打印出来两个对象,可以发现他们其实是同一个对象

<function fengshan at 0x7f9b0c92f950>
<function fengshan at 0x7f9b0c92f950>

现在你就已经理解了装饰器的实现了,而且如果你跟着文中的代码敲一遍,你就已经写了一个装饰器,你只需要稍加修改,比方说,我们在wrapper内部执行接收的func,并且,在前后加上一些操作

def wrapper(func):
  print('在wrapper中执行func前')
  print(func())
  print('在wrapper中执行func后')
wrapper(fengshan)

返回

在wrapper中执行func前

出风

在wrapper中执行func后

如果你觉得很神奇,无法理解,可以回到风扇的图片重新再读一遍,当你理解了上述的代码之后,我们就可以加快速度,完成真正的装饰器的编写

用法

当你成功明白了函数被定义和调用的过程之后,我们开始考虑实际场景,上一段代码中我们还是改变了原有函数的调用

从调用fengshan变成了调用func(fengshan)

我们想要实现不改变原有代码和调用方式的情况下为原有函数添加前置或后置操作,就需要再优化一下我们的装饰器

def fengshan():
  print('出风')

def wrapper(func):
  def f():
    print('在wrapper中执行func前')
    func()
    print('在wrapper中执行func后')
  return f

fengshan = wrapper(fengshan)
fengshan()

为了看到执行过程,我们把fengshan内部的return改为print

返回

在wrapper中执行func前

出风

在wrapper中执行func后

这里我们的改变是在wrapper原有的实现中又包了一层方法f,再回想一下我们前面风扇的例子,现在当我们执行wrapper的时候,执行了什么?

wrapper(func)的返回,是一个函数对象f,这个函数对象的开关没有被打开,f中的代码不会被执行

我们又用同名的fengshan对象去接收了这个函数对象f,在最后一行打开fengshan的开关 -- fengshan(),这时候函数对象f中的代码,才刚被执行

如果看不懂的话,建议从风扇图片开始再看一遍,如果你看懂了,建议你也再看一遍,至此,我们就已经完成了一个装饰器,为了更方便使用装饰器,Python给我们提供了更简便的方法

def wrapper(func):
  def f():
    print('在wrapper中执行func前')
    func()
    print('在wrapper中执行func后')
  return f
@wrapper
def fengshan():
  print('出风')
fengshan()

返回

在wrapper中执行func前

出风

在wrapper中执行func后

补充知识

如果你已经理解了装饰器的执行逻辑,你也就会知道如何让装饰器支持带参数的方法,这也是我们写装饰器的常规操作

def wrapper(func):
  def f(*args, **kwargs):
    print('在wrapper中执行func前')
    func(*args, **kwargs)
    print('在wrapper中执行func后')
  return f
@wrapper
def fengshan(str_obj):
  print(str_obj)
fengshan(str_obj='出风')

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Python函数装饰器原理与用法详解

    本文实例讲述了Python函数装饰器原理与用法.分享给大家供大家参考,具体如下: 装饰器本质上是一个函数,该函数用来处理其他函数,它可以让其他函数在不需要修改代码的前提下增加额外的功能,装饰器的返回值也是一个函数对象.它经常用于有切面需求的场景,比如:插入日志.性能测试.事务处理.缓存.权限校验等应用场景.装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用.概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能. 严格来说,装饰器只是语法糖,

  • Python unittest装饰器实现原理及代码

    1.前言 前面讲到unittest里面setUp可以在每次执行用例前执行,这样有效的减少了代码量,但是有个弊端,比如打开浏览器操作,每次执行用例时候都会重新打开,这样就会浪费很多时间. 于是就想是不是可以只打开一次浏览器,执行完用例再关闭呢?这就需要用到装饰器(@classmethod)来解决了. 2.@classmethod 装饰器中的 setUpClass() 和 tearDownClass() 与 setUp() 和 tearDown() 的区别 setUp():每个测试 case 运行之

  • python3 property装饰器实现原理与用法示例

    本文实例讲述了python3 property装饰器实现原理与用法.分享给大家供大家参考,具体如下: 学习python的同学,慢慢的都会接触到装饰器,装饰器在python里是功能强大的语法.装饰器配合python的魔法方法,能实现很多意想不到的功能.废话不多说,如果你已经掌握了闭包的原理,代码的逻辑还是可以看明白的,咱们直接进入正题. property的意义 @property把一个类的getter方法变成属性,如果还有setter方法,就在setter方法前面加上@method.setter.

  • Python装饰器结合递归原理解析

    代码如下: import functools def memoize(fn): print('start memoize') known = dict() @functools.wraps(fn) def memoizer(*args): if args not in known: print('memorize %s'%args) # known[args] = fn(*args) for k in known.keys(): print('%s : %s'%(k, known[k]), en

  • Python装饰器原理与用法分析

    本文实例讲述了Python装饰器原理与用法.分享给大家供大家参考,具体如下: 1.装饰器的本质是函数,主要用来装饰其他函数,也就是为其他函数添加附加功能 2.装饰器的原则: (1) 装饰器不能修改被装饰的函数的源代码 (2) 装饰器不能修改被装饰的函数的调用方式 3.实现装饰器的知识储备 (1) Python中函数即'变量' a.变量在Python中的存储 x='Tomwenxing' y=x [说明]: 当Python解释器遇到语句x='Tomwenxing'时,它主要完成了两样工作: 1.在

  • Python @property装饰器原理解析

    这篇文章主要介绍了Python @property装饰器原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.通过@property装饰器,可以直接通过方法名来访问方法,不需要在方法名后添加一对"()"小括号. class Person: def __init__(self, name): self.__name = name @property def say(self): return self.__name xioabai

  • Python自定义装饰器原理与用法实例分析

    本文实例讲述了Python自定义装饰器原理与用法.分享给大家供大家参考,具体如下: 什么是装饰器?装饰器本质是一个函数,它可以在不改变原来的函数的基础上额外的增加一些功能.如常见的@classmethod,@staticmethod等都是装饰器,接下来记录下如何自定义个装饰器: 刚刚说过了,装饰器的本质就是一个函数,所有想要自定义一个装饰器,首先自定义一个函数 def decorate(func): def wrapper(*args,**kwargs): print("定义一个装饰器"

  • Python3.5装饰器原理及应用实例详解

    本文实例讲述了Python3.5装饰器原理及应用.分享给大家供大家参考,具体如下: 1.装饰器: (1)本质:装饰器的本质是函数,其基本语法都是用关键字def去定义的. (2)功能:装饰其他函数,即:为其他函数添加附加功能. (3)原则:不能修改被装饰的函数的源代码,不能修改被装饰的函数的调用方式.即:装饰器对待被修饰的函数是完全透明的. (4)简单应用:统计函数运行时间的装饰器 import time #统计函数运行时间的砖装饰器 def timmer(func): def warpper(*

  • 通俗易懂了解Python装饰器原理

    作用 装饰器可以用于用于装饰一个函数或方法,使得在不修改原函数.方法代码的前提下,为方法添加前置或后置操作: 例如突然想要计算一下各个函数的执行时间,又不希望在每一个函数中添加tim.time()来计算执行时间 用法 装饰器的写法网上很多,但是我觉得还是尽量先理解,再知道怎么写会比较好,所以会先说如何理解,在后面重写用法 实现 了解装饰器是如何实现的,远比会写装饰器更重要,简单的说装饰器就是接收一个函数对象,然后先执行前置操作,再执行函数,再执行后置操作: 这么说可能有些抽象,或者举一个不那么恰

  • Python装饰器原理与简单用法实例分析

    本文实例讲述了Python装饰器原理与简单用法.分享给大家供大家参考,具体如下: 今天整理装饰器,内嵌的装饰器.让装饰器带参数等多种形式,非常复杂,让人头疼不已.但是突然间发现了装饰器的奥秘,原来如此简单.... 第一步 :从最简单的例子开始 # -*- coding:gbk -*- '''示例1: 使用语法糖@来装饰函数,相当于"myfunc = deco(myfunc)" 但发现新函数只在第一次被调用,且原函数多调用了一次''' def deco(func): print(&quo

  • Python 装饰器原理、定义与用法详解

    本文实例讲述了Python 装饰器原理.定义与用法.分享给大家供大家参考,具体如下: Python 装饰器 一.何为装饰器 1.在函数中定义函数 在函数中定义另外的函数,就是说可以创建嵌套的函数,例子如下 def sayHi(name="hjj2"): print 'inside sayHi() func' def greet(): return 'inside greet() func' print(greet()) sayHi() #output # inside sayHi()

  • 简单了解python装饰器原理及使用方法

    这篇文章主要介绍了简单了解python装饰器原理及使用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 如果你接触 Python 有一段时间了的话,想必你对 @ 符号一定不陌生了,没错 @ 符号就是装饰器的语法糖. 装饰器的使用方法很固定: 先定义一个装饰函数(帽子)(也可以用类.偏函数实现) 再定义你的业务函数.或者类(人)最后把这顶帽子带在这个人头上 Python装饰器就是用于拓展原来函数功能的一种函数,目的是在不改变原函数名(或类名)的

  • python装饰器原理与用法深入详解

    本文实例讲述了python装饰器原理与用法.分享给大家供大家参考,具体如下: 你会Python嘛? 我会! 那你给我讲下Python装饰器吧! Python装饰器啊?我没用过哎 以上是我一个哥们面试时候发生的真实对白. ----------------------------------------------分割线------------------------------------------------------------------------------ 简言之,python装饰

  • Python装饰器原理与基本用法分析

    本文实例讲述了Python装饰器原理与基本用法.分享给大家供大家参考,具体如下: 装饰器: 意义:在不能改变原函数的源代码,和在不改变整个项目中原函数的调用方式的情况下,给函数添加新的功能 由于不允许改变函数的源代码,在忽略调用方式的情况下,我们可能会有以下结果: def decorator(func): func() print("logging") def test1(): print("test1") def test2(): print("Test

  • python 装饰器(Decorators)原理说明及操作代码

    目录 1 必要的2个核心操作 1.1 核心操作1, 函数内部可以定义函数 1.2 核心操作2 函数可以作为对象被输入输出 1.2.1 核心操作2的前置条件,函数是对象 1.2.2函数作为输入 1.2.3 函数作为输出 2 尝试构造装饰器 3装饰器定义的简写 本文目的是由浅入深地介绍python装饰器原理 装饰器(Decorators)是 Python 的一个重要部分 其功能是,在不修改原函数(类)定义代码的情况下,增加新的功能 为了理解和实现装饰器,我们先引入2个核心操作: 1 必要的2个核心操

  • python装饰器原理源码示例分析

    目录 前言 一.什么是装饰器 二.为什么要用装饰器 三.简单的装饰器 四.装饰器的语法糖 五.装饰器传参 六.带参数的装饰器 七.类装饰器 八.带参数的类装饰器 九.装饰器的顺序 前言 最近有人问我装饰器是什么,我就跟他说,其实就是装饰器就是类似于女孩子的发卡.你喜欢的一个女孩子,她可以有很多个发卡,而当她戴上不同的发卡,她的头顶上就是装饰了不同的发卡.但是你喜欢的女孩子还是你喜欢的女孩子.如果还觉得不理解的话,装饰器就是咱们的手机壳,你尽管套上了手机壳,但并不影响你的手机功能,可你的手机还是该

随机推荐