本文作者:Rocky0249

公众号:Python空间


写在之前

「装饰器」作为 Python 高级语言特性中的重要部分,是修改函数的一种超级便捷的方式,适当使用能够有效提高代码的可读性和可维护性,非常的便利灵活。

「装饰器」本质上就是一个函数,这个函数的特点是可以接受其它的函数当作它的参数,并将其替换成一个新的函数(即返回给另一个函数)。

可能现在这么看的话有点懵,为了深入理解「装饰器」的原理,我们首先先要搞明白「什么是函数对象」,「什么是嵌套函数」,「什么是闭包」。

装饰器

搞明白上面的三个问题,其实简单点来说就是告诉你:函数可以赋值给变量,函数可嵌套,函数对象可以作为另一个函数的参数

首先我们来看一个例子,在这个例子中我们用到了前面列出来的所有知识:

def first(fun):    def second():                print('start')                fun()                print('end')        print fun.__name__    return second

def man():        print('i am a man()')

f = first(man)f()

上述代码的执行结果如下所示:

starti am a man()endman

上面的程序中,这个就是 first 函数接收了 man 函数作为参数,并将 man 函数以一个新的函数进行替换。看到这你有没有发现,这个和我在文章刚开始时所说的「装饰器」的描述是一样的。既然这样的话,那我们就把上述的代码改造成符合 Python 装饰器的定义和用法的样子,具体如下所示:

def first(func):    def second():               print('start')               func()               print('end')        print (func.__name__)    return second

@firstdef man():       print('i am a man()')

man()

上面这段代码和之前的代码的作用一模一样。区别在于之前的代码直接“明目张胆”的使用 first 函数去封装 man 函数,而上面这个是用了「语法糖」来封装 man 函数。至于什么是语法糖,不用细去追究,你就知道是类似「@first」这种形式的东西就好了。

在上述代码中「@frist」在 man 函数的上面,表示对 man 函数使用 first 装饰器。「@」 是装饰器的语法,「first」是装饰器的名称。

下面我们再来看一个复杂点的例子,用这个例子我们来更好的理解一下「装饰器」的使用以及它作为 Python 语言高级特性被人津津乐道的部分:

def check_admin(username):    if username != 'admin':                raise Exception('This user do not have permission')

class Stack:    def __init__(self):        self.item = []

    def push(self,username,item):                check_admin(username=username)        self.item.append(item)

    def pop(self,username):                check_admin(username=username)        if not self.item:                        raise Exception('NO elem in stack')        return self.item.pop()

上述实现了一个特殊的栈,特殊在多了检查当前用户是否为 admin 这步判断,如果当前用户不是 admin,则抛出异常。上面的代码中将检查当前用户的身份写成了一个独立的函数 check_admin,在 push 和 pop 中只需要调用这个函数即可。这种方式增强了代码的可读性,减少了代码冗余,希望大家在编程的时候可以具有这种意识。

下面我们来看看上述代码用装饰器来写成的效果:

def check_admin(func):    def wrapper(*args, **kwargs):        if kwargs.get('username') != 'admin':                        raise Exception('This user do not have permission')        return func(*args, **kwargs)    return wrapper

class Stack:    def __init__(self):        self.item = []

        @check_admin    def push(self,username,item):        self.item.append(item)

        @check_admin    def pop(self,username):        if not self.item:                        raise Exception('NO elem in stack')        return self.item.pop()

对比一下使用「装饰器」和不使用装饰器的两种写法,乍一看,好像使用「装饰器」以后代码的行数更多了,但是你有没有发现代码看起来好像更容易理解了一些。在没有装饰器的时候,我们先看到的是 check_admin 这个函数,我们得先去想这个函数是干嘛的,然后看到的才是对栈的操作;而使用装饰器的时候,我们上来看到的就是对栈的操作语句,至于 check_admin 完全不会干扰到我们对当前函数的理解,所以使用了装饰器可读性更好了一些

就和我在之前的文章中所讲的「生成器」那样,虽然 Python 的高级语言特性好用,但也不能乱用。装饰器的语法复杂,通过我们在上面缩写的装饰器就可以看出,它写完以后是很难调试的,并且使用「装饰器」的程序的速度会比不使用装饰器的程序更慢,所以还是要具体场景具体看待。

周末愉快~

相关阅读:

一文彻底搞懂 Python 生成器!

?扫描上方二维码关注小詹

面试系列 | 带你彻底搞懂 Python 装饰器相关推荐

  1. 怎么用Python写出随时间变化的字_面试必备 | 带你彻底搞懂 Python 生成器

    文章转载地址:面试必备 | 带你彻底搞懂 Python 生成器. 写在之前 Python 的高级语言特性一直是我们学习 Python 的一个难点,大部分人并没有做到熟练的掌握,甚至去学习它都感觉很困难 ...

  2. 面试必备|带你彻底搞懂Python生成器

    2019年人工智能系统学: https://edu.csdn.net/topic/ai30?utm_source=ai100_bw 作者 | Rocky0429 转载自 Python空间(ID:Dev ...

  3. python装饰器函数执行后日志_一篇文章搞懂Python装饰器所有用法

    如果你接触 Python 有一段时间了的话,想必你对 @ 符号一定不陌生了,没错 @ 符号就是装饰器的语法糖. 它放在一个函数开始定义的地方,它就像一顶帽子一样戴在这个函数的头上.和这个函数绑定在一起 ...

  4. 深入浅出 Python 装饰器:16 步轻松搞定 Python 装饰器

    2019独角兽企业重金招聘Python工程师标准>>> Python的装饰器的英文名叫Decorator,当你看到这个英文名的时候,你可能会把其跟Design Pattern里的De ...

  5. [译] 12步轻松搞定python装饰器 - 简书

    [译] 12步轻松搞定python装饰器 - 简书 呵呵!作为一名教python的老师,我发现学生们基本上一开始很难搞定python的装饰器,也许因为装饰器确实很难懂.搞定装饰器需要你了解一些函数式编 ...

  6. Python高级特性: 12步轻松搞定Python装饰器

    12步轻松搞定Python装饰器 通过 Python 装饰器实现DRY(不重复代码)原则:  http://python.jobbole.com/84151/ 基本上一开始很难搞定python的装饰器 ...

  7. 12步轻松搞定 Python 装饰器

    12步轻松搞定 Python 装饰器 1. 函数 在python中,函数通过def关键字.函数名和可选的参数列表定义.通过return关键字返回值.我们举例来说明如何定义和调用一个简单的函数: > ...

  8. python装饰器带参数函数二阶导数公式_一文搞定Python装饰器,看完面试不再慌

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是Python专题的第12篇文章,我们来看看Python装饰器. 一段囧事 差不多五年前面试的时候,我就领教过它的重要性.那时候我Pyt ...

  9. 利用世界杯,读懂 Python 装饰器

    Python 装饰器是在面试过程高频被问到的问题,装饰器也是一个非常好用的特性, 熟练掌握装饰器会让你的编程思路更加宽广,程序也更加 pythonic. 今天就结合最近的世界杯带大家理解下装饰器. 德 ...

最新文章

  1. Notepad2 一个很不错的记事本
  2. 读书狂想之《穷爸爸,富爸爸》财富观
  3. 查看linux中的sh指向哪,什么是Linux的Shell脚本和怎么执行脚本?
  4. DES密码实现( C语言 )
  5. VC2008以资源形式实现多语言版本
  6. Android tftp服务器,Ubuntu下配置TFTP服务以及 android下使用TFTP
  7. linux 创建交换文件格式,Linux系统下的交换分区和交换文件的含义 (创建交换分区文件基本文件的swap)...
  8. android lint
  9. OnlyOffice实现word转pdf
  10. reco-fetch
  11. 快递面单隐私保护教程
  12. 前端Vue简单编写一个幸运大转盘抽奖游戏
  13. 哪款蓝牙耳机跑步好用?跑步好用的耳机推荐
  14. 什么时候要把方法写成静态的。什么时候写成实例化方法。
  15. 思维导图FreeMind
  16. 中国银联-银星计划面试经历
  17. PS-InSAR大型机场变形监测
  18. MQTT移植到stm32开发板——使用TencentOS tiny操作系统
  19. ffmpeg中av_log的实现分析
  20. 【mpvue】小程序开发入门

热门文章

  1. windows下安装php性能分析工具XHProf(windows版本)
  2. Vue中ref的用法:获取DOM 父获取子数据 父使用子方法 子调用父方法
  3. linux 内核驱动的poll,嵌入式Linux驱动开发(五)——poll机制原理以及驱动实现...
  4. php mysql通用类_PHP连接MYSQL数据库通用类_PHP教程
  5. 中国语言文学专业c刊排行榜,中国有名的文学刊物有哪些 十大中国著名文学刊物盘点...
  6. 不会英语能学oracle吗,英语非常差该怎么学啊?
  7. 适合pythonpandas的软件_适合 Python 入门的 8 款强大工具!
  8. c#如何通过ftp上传文件_ftp自动上传文件,如何设置ftp自动上传文件及环境配置...
  9. oracle 计划名称,甲骨文修改合作伙伴计划 分为四个级别
  10. yum 错误:Invalid configuration value: failovermethod=priority