本章目录:

    装饰器:

        一、为什么要用装饰器

        二、什么是装饰器

        三、无参装饰器

        四、装饰器语法糖

        五、认证装饰器实现

        六、叠加多个装饰器

        七、带参装饰器   

===========================================================

一、开放封闭原则

  引子--为什么要用装饰器

  软件一旦上线后,对修改源代码是封闭的,对功能扩展是开放的。

  也就是说我们必须找到一种解决方案:

    能够在不修改一个功能源代码以及调用方式的前提下,为其加上新功能

    

    总结,原则如下:

      1、不修改源代码

      2、不修改调用方式

    目的:

      在原则1&2的基础上扩展新功能

二、什么是装饰器

  装饰器(Decorator)是一种特殊的函数,用来给函数添上新功能的函数。

  主要用于抽离大量函数中与函数本身无关的雷同代码并继续重用。

  装饰器又可分为带参数和不带参数。

  完整含义:

  装饰器即在不修改被装饰对象源代码与调用方式的前提下,为被装饰器对象添加新功能

  装饰器与被装饰对象均可以是任意可调用的对象

  装饰器>>>函数

  被装饰的对象>>>函数

三、装饰器实现之无参装饰器

  装饰器的实现不能脱离,不能修改源代码,不能修改源调用方式的原则。下面我们将按照实现装饰器的思路,一步一步实现装饰器。

  为下面的程序增加运行计时功能。

import time

def index():

   time.sleep()
print('This is Index Page!')

  方案1:

import time

def index():
start_time=time.time()
time.sleep(3)
print('welcome to index page')
stop_time=time.time()
print('run time is %s' %(stop_time-start_time)) index()
# 该方案虽然达到了计时功能,但是修改了源代码,违背了装饰器两大原则

  方案2:

import time   #引入时间包,方便调用time()方法

def index():
time.sleep(2)
print('This is Index Page.') start_time = time.time()
index()
stop_time = time.time()
print('The running time is %s' % (stop_time - start_time)
# 该方案虽然达到了计时功能,但是只是针对的增加代码,如果别的程序也要计时,还要重写一次,无法复用。

  方案3:

import time

def index():
time.sleep(2)
print('This is Index Page') def wrapper():
  start_time = time.time()
  index()
  stop_time = time.time()
  print('The running time is %s' % (stop_time - start_time))
# 该方案虽然达到了计时功能,但是要显示计时,还要去调用wrapper(),更改了原函数的调用方式

  方案4:

import time

def index():
time.sleep(2)
print('This is Index Page') def wrapper(func): #func = index start_time = time.time()
func(); #index
stop_time = time.time()
print('The running time is %s' % (stop_time, start_time)) wrapper(index)
# 该方案虽然达到了计时功能,但是要显示计时,不仅要调用wrapper(), 而且需要把原函数index作为参数导入,更改了原函数的调用方式

  方案5(步入正轨之无参装饰器):

import time

def index():
time.sleep()
print('This is Index Page') def outter(func): # func = 最初始的index
# func = index 巧用闭包,传递参数,
# 外部函数带的参数,就是准备给内部函数里用的,这里是闭包功能
def wrapper():
start_time = time.time()
func()
stop_time = time.time()
print('The running time is %s')
return wrapper index = outter(index) #初始index函数经过处理已经被变更为outter(index),被''装饰''了 index()
# 该方法能显示运行时长, 是把最初始的index函数通过闭包的特点,经过处理后重新把新的函数内存地址,赋值给了index,后面的index函数已经不是最初的index,它经过被''装饰''了

  方案6(方案5的升级版):

    1. 无参装饰器,引入带参函数的时候出现了错误。

# 不同于index()函数,这次我们引入一个新函数,带参数call_you(name)
import time def call_you(name):
time.sleep(2)
print('I call you %s' %name) def outter(func): def wrapper(name):
start_time = time.time()
res = func(name)
stop_time = time.time()
print('The running time is %s' % (stop_time - start_time)
return res return wrapper index = outter(index)
home = outter(home) #home带参,但是index不带参,这里运行会报错

  方案7(解决方案6的问题):

# 运用可变长度参数处理这个问题
# 可变长度参数模版,注意参数是*args  **kwargs

def outter(func):

    def inner(*args, **kwargs):
res = func(*args, ** kwargs)
return res return inner
import time

def call_you(name):
time.sleep(2)
print('I call you %s' %name) def outter(func): def wrapper(*args, **kwargs):
start_time = time.time()
res = func(*args, **kwargs)
stop_time = time.time()
print('The running time is %s' %(stop_time - start_time))
return res
return wrapper

call_you = outter(call_you) call_you('Puppy')

四、装饰器语法糖

  语法糖意指那些没有给计算机添加新功能,只是对人类来说更加“甜蜜”的语法,能够增加程序的可读性,减少代码出错的机会。

# 注意语法糖的放置位置,放在要用的函数的顶部,要用@开头

五、认证装饰器实现

  1. 加入认证模块的简单实现:

  2. 加入认证模块后登陆进行验证:

 

六、叠加多个装饰器
# 注意多个装饰器的顺序,按照顺序执行

  1. 认证装饰器

  

  2. 计时装饰器

  

  3. 叠加多个装饰器(注意先后顺序)

七、带参装饰器
 
带参数,可以让装饰器有更大的灵活性。上面写的无参装饰器唯一的参数就是执行对应的业务函数。装饰器的语法允许我们在调用的时候,提供其他参数。新增的参数为装饰器的编写和使用提供了更大的灵活性。
 
 
上面的use_logging是允许带参数的装饰器。它实际上是对原有装饰器的 一个函数封装,并返回一个装饰器。我们可以将它理解为一个含有参数的闭包。
当我们调用的时候,Python能够发现这一层封装,并把参数传递到装饰器的环境中。

Python入门之函数的装饰器的更多相关文章

  1. Python入门day04_函数与装饰器

    一.函数入门 什么是函数: # 函数:函数是一系列代码的集,用来完成特定功能的代码块,类似于工具,可以重复不但的去使用 为什么要有函数: # 优点:# 1. 避免代码的冗余 # 2. 让程序代码结构更 ...

  2. Python基础之函数与装饰器

    阅读目录 一.为什么要使用函数 二.函数的定义与调用 三.函数返回值 四.函数的参数 五.本章小结 六.装饰器 一.函数流程图: 函数名的命名规则: 1.函数名必须由字母下划线数字组成,不能是关键字和 ...

  3. python基础-闭包函数和装饰器

    闭包函数和装饰器 闭包函数 概念:在函数中(嵌套)定义另一个函数时,内部函数引用了外层函数的名字. 特性 闭包函数必须在函数内部定义 闭包函数可引用外层函数的名字 闭包函数是函数嵌套.函数对象.名称空 ...

  4. Python高阶函数之 - 装饰器

    高阶函数:  1. 函数名可以作为参数传入     2. 函数名可以作为返回值. python装饰器是用于拓展原来函数功能的一种函数 , 这个函数的特殊之处在于它的返回值也是一个函数 , 使用pyth ...

  5. Python全栈开发之路 【第五篇】:Python基础之函数进阶(装饰器、生成器&迭代器)

    本节内容 一.名称空间 又名name space,就是存放名字的地方.举例说明,若变量x=1,1存放于内存中,那名字x存放在哪里呢?名称空间正是存放名字x与1绑定关系的地方. 名称空间共3种,分别如下 ...

  6. Python之闭包函数、装饰器

    1.闭包函数 #作用域关系在函数定义阶段时就已经固定死了,与调用位置无关 # 即:在任意位置调用函数都需要跑到定义函数时寻找作用域关系 # def f1(): # x=1 # def inner(): ...

  7. Python学习之--函数/生成器/装饰器

    Function,函数,主要是为了:1提高代码的复用程度,2将程序模块化. 定义函数 在Python中,使用def 用来定义函数,一般函数的定义如下: def name(arg1,arg2,....) ...

  8. python 高阶函数与装饰器

    高阶函数定义1.函数接收的参数是一个函数名2.函数的返回值是一个函数名以上两者满足任意一个,就是高阶函数装饰器定义本质就是函数,功能是为其他函数添加新功能 装饰器的原则 1.不修改被装饰函数的源代码( ...

  9. python中高阶函数与装饰器(3)

    >>> f = lambda x: x * x>>> f<function <lambda> at 0x101c6ef28> >> ...

随机推荐

  1. nginx的自动化安装和启停脚本

    个人原创,转载请注明出处和作者,否则依法追究法律责任 author: headsen chen date:  2018-03-07  14:39:11 nginx_install.sh #!/bin/ ...

  2. 关于IPFS, 你想知道的都在这里

        IPFS的的"宏伟"目标是取代HTTP, 那么先来看看IPFS是如何工作的? IPFS为每一个文件分配一个独一无二的哈希值(文件指纹: 根据文件的内容进行创建), 即使是两 ...

  3. generator生成器iterator遍历器和yield

    generator方法()返回一个iterator 使用generator时永远先去调用generator()方法 for of对iterator的调用过程(babel参照) 1,_iterator. ...

  4. VS调试再次遭遇“应用程序中断模式”问题,附解决方法

    最近重构某项目过程中发现的,有同事反馈调试不正常,很久以前也发生过,虽然搜索了一下找到解决方案,但个人觉得还是有必要再记录一下. 调试某CS结构的应用程序,大致效果可以看下图: 我们组最终解决方案是: ...

  5. C语言第一次博客作业

    一,PTA实验作业 题目1.温度转换 本题要求编写程序,计算华氏温度150°F对应的摄氏温度.计算公式:C=5×(F−32)/9,式中:C表示摄氏温度,F表示华氏温度,输出数据要求为整型. 1.实验代 ...

  6. redis备份与恢复

    1.redis的备份 redis需要远程访问 添加密码进行登录,修改主配置文件添加:requirepass xxx redis-cli -h 127.0.0.1 -p 6379 -a 123456 b ...

  7. SDK提交到CocoaPods

    一:GitHub新建仓库,并clone到本地 1.注册GitHub账号并登录 2.右上方点击+,新建仓库(仓库名字(Repository name).仓库权限(Public).readme.licen ...

  8. lua 二维数组创建

    local arr= {} for i=1, 4 do arr[i] = {} end 使用时可以直接使用arr[i][j]

  9. Vim编辑器的注释,解注,删除与恢复

    1. 注释: 将光标移动到注释首部 命令模式下 Ctrl+V,进入列模式 上下移动,选中待注释内容 按大写I,进入插入模式 输入 // or # 按两次退出 2 解注 将光标移动到待解注首部 命令模式 ...

  10. ThreadLocal 原理和使用场景分析

    ThreadLocal 不知道大家有没有用过,但至少听说过,今天主要记录一下 ThreadLocal 的原理和使用场景. 使用场景 直接定位到 ThreadLocal 的源码,可以看到源码注释中有很清 ...