1.装饰器的概念

  装饰器本质上就是一个函数,主要是为其他的函数添加附加的功能,装饰器的原则有以下两个:

  • 装饰器不能修改被修饰函数的源代码
  • 装饰器不能修改被修改函数的调用方式  

  装饰器可以简单的理解为:高阶函数+嵌套函数+闭包


2.高阶函数

  高阶函数我在前面的博客中已经讲过了,在这里我再简单的说一下吧。
  高阶函数:如果一个函数接收的参数是一个函数名,或者返回值是函数名,只要满足任意一个条件,这个函数就称为高阶函数。

  • 接收的参数是一个函数名
def foo():print("the result from foo")
def bar(func):func()print("the result from bar")
bar(foo)  

  在上面的例子中,我定义了两个函数,foo()和bar(),在调用bar()函数的时候,我将foo()作为一个参数传给了bar(),运行就会得到foo()的结果,这样的函数就可以成为高阶函数。

  • 返回值是一个函数名
def foo():print("the result from foo")
def bar(func):return func
bar(foo)

  调用bar()函数 返回的就是foo()的内存地址,这也可以称为高阶函数。


3.函数嵌套

  函数嵌套:函数嵌套我在前面也已经讲过了,其实就是函数的内部再声明函数,很好理解的一个概念,举个例子:如下

def foo():print("the result from foo")def bar():print("the result from bar")bar()
foo()

  在上面这个例子中,我在函数foo()的内部又写了一个bar()函数,并在下面调用了该函数,这种方式就叫做函数嵌套,可以嵌套很多层,只要注意函数缩进问题


4.闭包

  在Python中闭包的表现形式可以理解为:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure)。
  单从上面的定义可能很难理解,我下面用一个简单的程序说明一下:

def foo():a=1b=2def bar():c=3return a+b+creturn bar
print(foo()())

  在上面这个例子中,bar()就是foo()的一个内部函数,在bar()的局部作用于可以直接使用foo()的局部变量a,b,简单的说,这种内部函数可以访问外部函数变量的行为,就叫做闭包。


4.装饰器实例

  为了能让大家更好的理解装饰器,我会分步做出这个实例。

  • 装饰器的基本实现

  先定义一个函数name(),3秒后打印名字

import time
def name():time.sleep(2)print("my name is 尼古拉斯赵四")
name()

  现在有一个需求,我想要统计这个函数一个运行了多少秒,在不修改源代码的情况下,就需要给这个函数写一个装饰器来完成这个需求。

def timmer(func):       #定义一个形参,就是为了接受name()这个函数,注意前面文章就已经强调过的:函数即变量---func=namedef wapper():       #定义函数wapper(),用来接收name的参数start_time=time.time()func()          #实质上就是在运行test()       stop_time=time.time()print("name()函数一共运行了%s 秒"%(stop_time-start_time))return wapper       import time
@timmer             #使用装饰器的方法,通过@+作为装饰器的那个函数名
def name():time.sleep(2)print("my name is 尼古拉斯赵四")
name()
运行结果:
my name is 尼古拉斯赵四
name()函数一共运行了2.0002381801605225 秒

  上面这个例子就是一个简单的装饰器,没有修改原函数的调用方法和返回值,装饰器timmer中用到了高阶函数+函数嵌套+闭包的知识,ok,完美。

  • 在装饰器中添加参数
      上面的例子是完美的实现了所需要的功能,但是问题来了,如果原函数是现在这样呢?
def name(my_name,my_age):time.sleep(2)print("my name is %s,my age is %s"%(my_name,my_age))
name("尼古拉斯赵四",18)

  我需要随机传入两个值,打印出他的姓名和年龄,如果原函数这样调用,使用上面的装饰器肯定会出错,那就需要在装饰器函数中做如下修改:def wapper(my_name,my_age)func(my_name,my_age)这两行加入相同的参数,也是可以的,但如果name函数我再修改呢,不传入两个参数了 ,传3个 或更多,每次都要去修改岂不是很麻烦,这就需要做一些改变了 。

def timmer(func):      def wapper(*args,**kwargs):         #这里用*args,**kwargs代替,这样 ,不管原函数传入多少个参数,都可以匹配start_time=time.time()func(*args,**kwargs)             #同样,接受任意多个参数 (如果不懂这个什么意思,翻看我前面函数篇的博客,有讲到)stop_time=time.time()print("name()函数一共运行了%s 秒"%(stop_time-start_time))return wapper

  • 装饰器添加返回值
      参数问题解决了,下面我的原函数又变了
def name(my_name,my_age):time.sleep(2)print("my name is %s,my age is %s"%(my_name,my_age))return "尼古拉斯  你真年轻"
print(name("尼古拉斯赵四",18))
运行结果:
my name is 尼古拉斯赵四,my age is 18
尼古拉斯  你真年轻

  在这个函数中,我需求是在运行完函数返回"尼古拉斯 你真年轻"这句话,还是用上面的装饰器返回值会是my name is 尼古拉斯赵四,my age is 18 name()函数一共运行了2.000795364379883 秒 None,返回值是None而不是想要的结果,大家可以试一下,所以要加如下修改:

def timmer(func):def wapper(*args,**kwargs):         start_time=time.time()res=func(*args,**kwargs)            #将func()运行结果赋值给变量resstop_time=time.time()print("name()函数一共运行了%s 秒"%(stop_time-start_time))return res                          #返回res,其实就是在返回name()return wapper

  上面就详细写了装饰器的实现过程,就先写到这,后续我会丰富装饰器并做出一个通俗易懂的例子供大家参考,稍后一些时间也会发布在我的博客里,感兴趣的到时候可以看一下,希望可以帮助大家对装饰器有更好的理解。

转载于:https://www.cnblogs.com/Chen-Zhipeng/p/8035938.html

Python函数篇(5)-装饰器及实例讲解相关推荐

  1. pythonproperty装饰器_实例讲解Python编程中@property装饰器的用法

    取值和赋值 class Actress(): def __init__(self): self.name = 'TianXin' self.age = 5 类Actress中有两个成员变量name和a ...

  2. python函数基础和装饰器

    一.为什么要有函数?没有函数有什么问题? 1.组织结构不清晰,可读性差 2.代码冗余 3.可扩展性差 二.函数的分类: 1.内置函数:python解释器已经为我们定义好了的函数即内置函数,我们可以拿来 ...

  3. itext生成pdf paragraph 自动换行_reportlab高级制作多格式PDF和python的class和装饰器复习

    1 说明 1.1 reportlab高级制作多格式PDF:即包含文字.表格.柱状图. 1.2 复习python的class和装饰器的高级基础知识. 1.3 列表转换字符串.读取txt文件等python ...

  4. python装饰器实例-python装饰器使用实例详解

    这篇文章主要介绍了python装饰器使用实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 python装饰器的作用就是在不想改变原函数代码的情 ...

  5. python装饰器详解51-python装饰器使用实例详解

    这篇文章主要介绍了python装饰器使用实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 python装饰器的作用就是在不想改变原函数代码的情 ...

  6. python装饰器详解-python装饰器使用实例详解

    这篇文章主要介绍了python装饰器使用实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 python装饰器的作用就是在不想改变原函数代码的情 ...

  7. python函数装饰函数_Python精进-装饰器与函数对象

    本文为<爬着学Python>系列第四篇文章. 从本篇开始,本专栏在顺序更新的基础上,会有不规则的更新. 在Python的学习与运用中,我们迟早会遇到装饰器,这个概念对于初识装饰器的新手来说 ...

  8. python: 从函数了解到装饰器

    Table of Contents 1. 简单了解函数 1.1. 函数是什么 1.2. 函数的好处 1.3. 函数和过程的区别 1.3.1. python的函数和过程 1.3.2. common li ...

  9. python log函数_python要点-装饰器

    大家有没有碰到过这种需求,扩展公司的历史项目,对功能进行扩展?拿到历史项目看源码的时候是不是头特别大,难上加难的是还要对其进行修改!!!今天要讲的是python中的重要功能-装饰器,其对满足前述的实现 ...

最新文章

  1. 全国计算机一级office2010,2018年全国计算机等级考试一级office2010真题一套(中档题)...
  2. Android的Crash崩溃解决方案-Bugly的使用
  3. linux——NFS+AUTOFS服务的基本配置
  4. (原创).Net将EF运用于Oralce一 准备工作
  5. gradle 查看依赖类库版本_Android studio中查看依赖的第三方库的历史版本和最新版本...
  6. 查找 - 计算式查找法 - 哈希法
  7. 谷歌修复已遭利用的 Chrome 0day
  8. 在php中插入图片,php中怎么插入图片
  9. array,集合(collection),集合(list)的区别
  10. 毕设查重,避免雷区【划重点!!!】
  11. 347,猜数字大小 II
  12. java.lang.IllegalStateException: Only fullscreen opaque activities can request orientation
  13. 记一次前端实习生面试
  14. Ubuntu下如何使用编译使用john-1.9.0源码
  15. LR 的上传文件与下载文件
  16. OPNET入门2-Basic Process
  17. 艾永亮:腾讯、阿里、网易云音乐竞争升级,谁将造就高收益的超级产品
  18. request.js?b775:43 Uncaught (in promise) Error: 抱歉,系统繁忙,请稍后重试! at __webpack_exports__.default (r
  19. How Much Should We Invest for Network Facility: Quantitative Analysis on Network ’Fatness’ and Machi
  20. [组图教程]:8大方法!解决CPU资源占用100%[ZT]

热门文章

  1. Session与Cookie
  2. 在tomcat中部署web项目
  3. 微服务平台改造落地解决方案设计
  4. 编程语言圣经(卷一)
  5. 一个 .git 目录,领悟 Git 的强大!
  6. 史上最坑爹的代码!个个让人崩溃!
  7. 优秀程序员写代码一定会用的 11 条经验
  8. 咖啡馆的故事:FTP, RMI , XML-RPC, SOAP, REST一网打尽
  9. 面试必考-从URL输入到页面展现到底发生了什么
  10. 一分钟开启Tomcat https支持