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 ...
随机推荐
- 【编程之美】超时重传,滑动窗口,可靠性传输原理C语言实现
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://www.cnblogs.com/lihuidashen/p/128003 ...
- Asp.Net Core 3.1 的启动过程5
前言 本文主要讲的是Asp.Net Core的启动过程,帮助大家掌握应用程序的关键配置点. 1.创建项目 1.1.用Visual Studio 2019 创建WebApi项目. 这里面可以看到有两个关 ...
- php中session_id()函数详细介绍,会话id生成过程及session id长度
php中session_id()函数原型及说明session_id()函数说明:stringsession_id([string$id])session_id() 可以用来获取/设置 当前会话 ID. ...
- php原生函数应用
php常见基本的函数 一.字符串函数 implode — 将一个一维数组的值转化为字符串 lcfirst — 使一个字符串的第一个字符小写 ltrim — 删除字符串开头的空白字符(或其他字符) rt ...
- 2019-2020-1 20199325《Linux内核原理与分析》第三周作业
在实验楼当中进行实验3的实践:主要是针对cpu占用分配,使用时间片轮转算法进行分配 在Shell命令当中输入如下代码: $ cd ~/LinuxKernel/linux-3.9.4 $ rm -rf ...
- POJ2044 天气预报---状态细则
墙角数枝梅,凌寒独自开. 遥知不是雪,为有暗香来.--王安石 题目:天气预报 网址:http://poj.org/problem?id=2044 你是一个可以控制降雨的神仙. 你是一个仁慈的神,希望土 ...
- Linux系统管理第三次作业 账号管理 权限及归属管理
1.创建/guanli 目录,在/guanli下创建zonghe 和 jishu 两个目录(一条命令) [root@localhost ~]# mkdir /guanli [root@localhos ...
- atom 之 前端必备插件
一. 语法支持 1. Language-label Ø ES2016.ESNext.JXS语法扩展 2. Language-postcss Ø Postcss语法高亮 二. 自动补全 1. Autoc ...
- 多线程——继承Thread 类和实现Runnable 接口的区别
java中我们想要实现多线程常用的有两种方法,继承Thread 类和实现Runnable 接口,有经验的程序员都会选择实现Runnable接口 ,其主要原因有以下两点: 首先,java只能单继承,因此 ...
- 《WCF技术内幕》翻译3:第1部分_第1章_蓝月亮:普遍需求和普遍概念
第一部分:WCF介绍 章节目录: 第1章:蓝月亮 第2章:面向服务 第3章:消息交换模式.拓扑和编排 第4章:WCF 101 第1章:蓝月亮 商业和市场对软件系统新 ...