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 ...
随机推荐
- python os模块获取指定目录下的文件列表
bath_path = r"I:\ner_results\ner_results" dir_list1 = os.listdir(bath_path) for dir1 in di ...
- 设置共享内存大小 【windows】
hMapFile = CreateFileMapping( INVALID_HANDLE_VALUE, // use paging file NULL, // default security PAG ...
- innobackupex 出现Unrecognized character \x01; marked by
centos 7.2 mysql 5.7.16 innobackupex version 2.4.6 [root@Devops-mysql-150-115 sh]# innobackupex --de ...
- Java本地的项目,怎么可以让别人通过外网访问-内网穿透
2019独角兽企业重金招聘Python工程师标准>>> 一.点击链接 https://natapp.cn/ 注册个免费的账户 NATAPP官网 二.登陆进去以后查看authtoken ...
- 《WCF技术内幕》翻译3:第1部分_第1章_蓝月亮:普遍需求和普遍概念
第一部分:WCF介绍 章节目录: 第1章:蓝月亮 第2章:面向服务 第3章:消息交换模式.拓扑和编排 第4章:WCF 101 第1章:蓝月亮 商业和市场对软件系统新 ...
- centos 7.0运行docker出现内核报错解决方法
目前我这里docker是运行在centos 7.0系统里,使用1.5版本docker,最近一台服务器总是不定期死机,通过查看日志发现属于内核bug导致,报错信息如下 1 2 3 4 5 6 7 8 9 ...
- struts2验证码
验证码大多是jsp,servlet写的. 我拿来主义了, 再自己完善了一下(我一直努力想要站在巨人的肩膀) 首先是页面 test.jsp <%@ page contentType=" ...
- INTERVIEW #0
一.造成网络延迟的可能原因 1,WiFi所有用户上下行流量共用一个信道,当用户太多或者有人在下载大的资源时带宽不够,丢包: 2,线路质量不佳导致信噪比太低,比如光纤损耗太大等. 二.IPv6优势 1, ...
- linux 进程管理和内存分配
1.进程相关概念 进程:正在运行中的程序 内核功用:进程管理.文件系统.网络功能.内存管理.驱动程序.安全功能等 Process:运行中的程序的一个副本,是被载入内存的一个指令集合 进程 ID(Pro ...
- DHCP报文(1)
DHCP报文 1.地址申请类型(4步工作原理,常考) (1)此题是典型的四步工作原理,在其配置过程中由于没有分配IP地址,用的是广播形式,所以其4中报文类型的目的IP地址均为255.255.255.2 ...