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 ...
随机推荐
- js判断一个元素是否在数组内
1.indexOf()返回给定元素在数组内的索引值,如果不存在则返回-1 var arr=[0,1,2,3,4,5] console.log(arr.indexOf(1)) console.log(a ...
- 免费 https 申请步骤,你必须知道
不适用 https 加密的网站,基本上就等于在裸奔. 来,开始开始动手做 我的系统是 CentOS6 第一步:安装Certbot Certbot可以用于管理(申请.更新.配置.撤销和删除等)Let's ...
- java 8 Streams简介
目录 简介 Functional Interface Function:一个参数一个返回值 BiFunction:接收两个参数,一个返回值 Supplier:无参的Function Consumer: ...
- composer+psr-4实现自动加载
自动加载 对于库的自动加载信息,Composer 生成了一个 vendor/autoload.php 文件.你可以简单的引入这个文件,你会得到一个免费的自动加载支持. require 'vendor/ ...
- JavaScript Array every()&some()&reduce()方法
every()方法测试数组的所有元素是否都通过了指定函数的测试. // 每一项都要满足条件才会返回true,只要有一项不满足返回false var arr = [1, 2, 3, 4]; let bl ...
- Docker 1.13.0 详细更新日志
本文讲的是Docker 1.13.0 详细更新日志[编者的话]Docker发布1.13.0版本,此次版本更新内容较多,以下为该版本具体的变更. 构建 添加在构建时可以指定镜像用作高速缓存源的功能. 这 ...
- 解析.xml并保存结点信息至.txt中
@ 思路 利用java开源库dom4j解析.xml: dom4j操作xml - 读取xml,生成一个document实例: SAXReader reader = new SAXReader(); Do ...
- MySQL分页查询的性能优化
MySQL limit分页查询的性能优化 Mysql的分页查询十分简单,但是当数据量大的时候一般的分页就吃不消了. 传统分页查询:SELECT c1,c2,cn… FROM table LIMIT n ...
- JVM之类加载器、加载过程及双亲委派机制
JVM 的生命周期 虚拟机的启动 Java 虚拟机的启动是通过引导类加载器(bootstrap class loader)创建一个初始类(initial class)来完成的,这个类是由虚拟机的具体实 ...
- Java——多线程超详细总结
该系列博文会告诉你如何从入门到进阶,一步步地学习Java基础知识,并上手进行实战,接着了解每个Java知识点背后的实现原理,更完整地了解整个Java技术体系,形成自己的知识框架. 一.线程概述 几乎所 ...