ql的python学习之路-day9
前言:本节主要学习装饰器
一、装饰器
定义:本质上是个函数,用来装饰其他函数;(就是为其他函数添加附加功能)
原则: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的更多相关文章
- ql的python学习之路-day15
前言:本节主要讲解的是文件路径 在实际的软件开发中会设计一个项目的文件目录,按照执行包bin.配置包config.核心包core等来设计,在执行包里面要运行核心包里的主程序mian,由于不在同一级的目 ...
- ql的python学习之路-day14
前言:本节主要学习时间模块time.datetime python中的几种时间表示:1)时间戳 2)格式化的字符串时间 3)struct_time元组格式的时间 time.datetime模块源码: ...
- ql的python学习之路-day13
前言:本节主要学习模块 一.模块的定义 模块:本质是.py结尾的python文件(文件名:test.py,对应的模块是:test),用来从逻辑上组织python代码(变量.函数.类.逻辑,本质是实现一 ...
- ql的python学习之路-day12
前言:这一节主要学习json和pickle 背景: 相信大家在日常生活中都有接触大型的网络游戏,打游戏的时候都是自己在电脑上操作,自己刷怪升级:当然也会碰到中午去吃饭然后挂机的情况,让电脑自动的刷怪, ...
- ql的python学习之路-day11
前言:本节主要学习python内置的方法 #!/usr/bin/env python # -*- coding:utf-8 -*- # Author:qinjiaxi from collections ...
- ql的python学习之路-day10
前言:本节主要讲解迭代器和生成器 迭代器&生成器 一.生成器(generator) 循环占用大部分的容量内存,如果只需要循环前面的几个结果那怎么样做呢,在python中有一种一边循环一边计算的 ...
- ql的python学习之路-day8
前言:本节主要学习的是函数的全局变量和局部变量以及递归 一.全局变量和局部变量 定义在函数外并且在函数头部的变量,叫做全局变量,全局变量在整个代码中都生效. 局部变量只在函数里生效,这个函数就叫做这个 ...
- ql的python学习之路-day7
函数与函数式编程 一.编程模式分为三种: 1.面向对象编程:类----->关键字class 2.面向过程编程:过程----->关键字def,没有return 3.函数式编程:函数----- ...
- ql的python学习之路-day6
字节编码: 这一节主要学习的是各种编码模式的相互转换,另外插两句话,今天的心情不是特别好,又没控制好自己的情绪,以后要心存阳光,好好的对待生活和身边的人. 废话不多说了直接贴码: #!/usr/bin ...
随机推荐
- PostMan接口测试(很全面的接口测试教程)
一:理论部分 1. 前言 在前后端分离开发时,后端工作人员完成系统接口开发后,需要与前端人员对接,测试调试接口,验证接口的正确性可用性.而这要求前端开发进度和后端进度保持基本一致,任何一方的进度跟不上 ...
- Pycharm 操作数据库
view--->Tool Buttons,点击Pycharm右侧的Database 1.连接数据库 2.建立一个表,添加数据 通过以上操作把用户名和密码储存到了数据库中 3.连 ...
- 曹工杂谈--只用一个命令,centos系统里装了啥软件,啥时候装的,全都清清楚楚
前言 一直以来,对linux的掌握就是半桶水的状态,经常yum装个东西,结果依赖一堆东西:然后再用源码装个东西,只知道make.make install,背后干了啥也不清楚了,卸载也不方便. 这几天工 ...
- SNMP History and OID/MIB Tour
https://www.pei.com/snmp-history-oid-mib/ Description: This document describes a bit of history and ...
- 以命令行界面启动 Ubuntu
1. /etc/default/grub 将GRUB_CMDLINE_LINUX_DEFAULT一行中改为"quiet splash 3" 2. update-grub 3. 重启
- centos 服务器上部署 xxl-job 通过 feign 访问 eureka 上注册的 service timeout
部署方式 1.使用 jar 包部署 出现的问题 1.通过 feign 调用其他服务,出现超时的问题,该问题不是 ribbon.hystrix 没有配置导致的超时,经过测试,即使配置了也没有作用,该方法 ...
- Maven Wrapper简介
文章目录 简介 Maven Wrapper的结构 下载Maven Wrapper 使用 Maven Wrapper简介 简介 开发java项目少不了要用到maven或者gradle,对比gradle而 ...
- 3.PEP 8是什么?
PEP 8是什么? PEP 8 is a coding convention, a set of recommendation, about how to write your Python code ...
- javascript SDK开发之webpack中eslint的配置
eslint的好处就不多说了.代码检查,代码报错, 智能提示,让开发人员更规范的撸代码等等. 1.安装依赖 npm install --save-dev eslint eslint-friendly- ...
- event兼容性解决
event出现undefind错误 解决方法: $('#normalImgDiv').mousemove(function (e) { var e = window.event || e; var p ...