前言:本节主要学习装饰器

一、装饰器

定义:本质上是个函数,用来装饰其他函数;(就是为其他函数添加附加功能)

原则:1.不能修改被装饰的函数的源代码

   2.不能修改被装饰的函数的调用方式

以上两点可以总结出装饰器对被装饰的函数来说是完全透明的,因为装饰器不能修改原函数的源代码,被装饰的函数还是像往常一样继续运行。

实现装饰器的知识储备:1.函数即‘变量’

           2.高阶函数

           3.嵌套函数

可以理解成:高阶函数 + 嵌套函数 = 装饰器

1.函数即‘变量’

内存回收机制:数据存储在内存中,用变量名来引用;如果把内存比作一栋大厦,数据比作一个房间,变量名相当于门牌号,用门牌号来访问房间;如果删除了变量名,在一段时间内没有引用数据,python的内存回收机制就会回收数据。

函数如同变量:函数和变量一样也有内存回收机制,在定义函数的时候相当于把函数体赋值给了函数名,在内存里面存储着函数体,然后用函数名来引用;匿名函数也是一样,在内存中存储lambda表达式,如果把lambda表达式赋值给一个变量名,就能用变量来引用lambda表达式。

2.高阶函数

满足下面任意一条就可以看做是高阶函数:

a:把一个函数名当做实参传给另外一个函数(在不修改被装饰函数源代码的情况下为其添加功能)

b:返回值中包含函数名(不修改函数的调用方式)

 #!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:qinjiaxi
import time def bar():
time.sleep(3)
print('in the test1') def test1(func):
start_time = time.time()
func()
stop_time = time.time()
print("time func run time is %s" % (stop_time-start_time)) test1(bar)

3.嵌套函数

在一个函数体内定义一个函数,而不是在一个函数里面调用函数,这个叫做函数的嵌套。

 #!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:qinjiaxi
x = 2
def grandpa():
x = 1
def father():
x = 2
def son():
x = 3
print(x)
son()
father()
grandpa()

返回值是3

4.装饰器实例

 #!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:qinjiaxi
import time
#timer是装饰器满足嵌套函数(函数里面定义一个函数),满足高阶函数(返回值有函数名)
def timer(func):
def deco(*args, **kwargs):
start_time = time.time()
func(*args, **kwargs)#run test1
stop_time = time.time()
print("the func run time is %s" % (stop_time - start_time))
return deco
@timer #test1 = timer(test1)#调用装饰器
def test1():
time.sleep(3)
print("in the test1")
test1()#这个不是上面这个test1函数,其实是运行deco这个内存地址

5.装饰器实例升级版

 #!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:qinjiaxi
import time
user, password = 'qinjiaxi', 'abc123'
def auth(auth_type):
print("auth func", auth_type)
def out_wrapper(func):
def wrapper(*args, **kwargs):
print("wrapper func args", *args, **kwargs)
if auth_type == "local":
username = input("Username:").strip()
passwd = input("Password:").strip()
if user == username and password == password:
print("\033[32;1mUser has passed authentication\033[0m")
res = func(*args,**kwargs)#from home
print("-----after authentication-----")
return res
else:
exit("\033[31;1mInvalid username or password\033[0m")
elif auth_type == 'ldap':
print("sorry I do not know")
return wrapper
return out_wrapper def index():
print("welcome to index page") @auth(auth_type='local')#home = wrapper /home = out_wrapper(home)
def home():
print("welcome to home page")
return "from home" @auth(auth_type="ldap")#bbs = wrapper
def bbs():
print("welcome to bbs page") index()
print(home())
bbs()

注:装饰器对于初学者来说还是比较难以理解的。实际多debug一下就会理解其中的原理,下面简单的分几个步骤剖析一下(拿上面的升级版实例来说明):

1.当调用装饰器时(实例中的@auth(auth_type = ‘xxxx’))其实程序运行时先找到调用装饰器的位置,从装饰器里面一步一步的return出最里层的函数的内存地址,也就是函数名(实例中的wrapper)

2.返回出最里层函数名后跳到最后面的调用函数部分(实例中最后三行)来调用函数(这个函数其实就是上面最里层的函数)

3.然后执行装饰器最里层的函数,执行到res = func(*args, **kwargs)时候就是调用被装饰的函数

ql的python学习之路-day9的更多相关文章

  1. ql的python学习之路-day15

    前言:本节主要讲解的是文件路径 在实际的软件开发中会设计一个项目的文件目录,按照执行包bin.配置包config.核心包core等来设计,在执行包里面要运行核心包里的主程序mian,由于不在同一级的目 ...

  2. ql的python学习之路-day14

    前言:本节主要学习时间模块time.datetime python中的几种时间表示:1)时间戳  2)格式化的字符串时间 3)struct_time元组格式的时间 time.datetime模块源码: ...

  3. ql的python学习之路-day13

    前言:本节主要学习模块 一.模块的定义 模块:本质是.py结尾的python文件(文件名:test.py,对应的模块是:test),用来从逻辑上组织python代码(变量.函数.类.逻辑,本质是实现一 ...

  4. ql的python学习之路-day12

    前言:这一节主要学习json和pickle 背景: 相信大家在日常生活中都有接触大型的网络游戏,打游戏的时候都是自己在电脑上操作,自己刷怪升级:当然也会碰到中午去吃饭然后挂机的情况,让电脑自动的刷怪, ...

  5. ql的python学习之路-day11

    前言:本节主要学习python内置的方法 #!/usr/bin/env python # -*- coding:utf-8 -*- # Author:qinjiaxi from collections ...

  6. ql的python学习之路-day10

    前言:本节主要讲解迭代器和生成器 迭代器&生成器 一.生成器(generator) 循环占用大部分的容量内存,如果只需要循环前面的几个结果那怎么样做呢,在python中有一种一边循环一边计算的 ...

  7. ql的python学习之路-day8

    前言:本节主要学习的是函数的全局变量和局部变量以及递归 一.全局变量和局部变量 定义在函数外并且在函数头部的变量,叫做全局变量,全局变量在整个代码中都生效. 局部变量只在函数里生效,这个函数就叫做这个 ...

  8. ql的python学习之路-day7

    函数与函数式编程 一.编程模式分为三种: 1.面向对象编程:类----->关键字class 2.面向过程编程:过程----->关键字def,没有return 3.函数式编程:函数----- ...

  9. ql的python学习之路-day6

    字节编码: 这一节主要学习的是各种编码模式的相互转换,另外插两句话,今天的心情不是特别好,又没控制好自己的情绪,以后要心存阳光,好好的对待生活和身边的人. 废话不多说了直接贴码: #!/usr/bin ...

随机推荐

  1. PostMan接口测试(很全面的接口测试教程)

    一:理论部分 1. 前言 在前后端分离开发时,后端工作人员完成系统接口开发后,需要与前端人员对接,测试调试接口,验证接口的正确性可用性.而这要求前端开发进度和后端进度保持基本一致,任何一方的进度跟不上 ...

  2. Pycharm 操作数据库

    view--->Tool Buttons,点击Pycharm右侧的Database 1.连接数据库       2.建立一个表,添加数据   通过以上操作把用户名和密码储存到了数据库中  3.连 ...

  3. 曹工杂谈--只用一个命令,centos系统里装了啥软件,啥时候装的,全都清清楚楚

    前言 一直以来,对linux的掌握就是半桶水的状态,经常yum装个东西,结果依赖一堆东西:然后再用源码装个东西,只知道make.make install,背后干了啥也不清楚了,卸载也不方便. 这几天工 ...

  4. SNMP History and OID/MIB Tour

    https://www.pei.com/snmp-history-oid-mib/ Description: This document describes a bit of history and ...

  5. 以命令行界面启动 Ubuntu

    1. /etc/default/grub 将GRUB_CMDLINE_LINUX_DEFAULT一行中改为"quiet splash 3" 2. update-grub 3. 重启

  6. centos 服务器上部署 xxl-job 通过 feign 访问 eureka 上注册的 service timeout

    部署方式 1.使用 jar 包部署 出现的问题 1.通过 feign 调用其他服务,出现超时的问题,该问题不是 ribbon.hystrix 没有配置导致的超时,经过测试,即使配置了也没有作用,该方法 ...

  7. Maven Wrapper简介

    文章目录 简介 Maven Wrapper的结构 下载Maven Wrapper 使用 Maven Wrapper简介 简介 开发java项目少不了要用到maven或者gradle,对比gradle而 ...

  8. 3.PEP 8是什么?

    PEP 8是什么? PEP 8 is a coding convention, a set of recommendation, about how to write your Python code ...

  9. javascript SDK开发之webpack中eslint的配置

    eslint的好处就不多说了.代码检查,代码报错, 智能提示,让开发人员更规范的撸代码等等. 1.安装依赖 npm install --save-dev eslint eslint-friendly- ...

  10. event兼容性解决

    event出现undefind错误 解决方法: $('#normalImgDiv').mousemove(function (e) { var e = window.event || e; var p ...