python全栈开发从入门到放弃之装饰器函数
什么是装饰器
#1 开放封闭原则:对扩展是开放的,对修改是封闭的
#2 装饰器本身可以是任意可调用对象,被装饰的对象也可以是任意可调用对象
#3 目的:
'''
在遵循
1. 不修改被装饰对象的源代码
2. 不修改被装饰对象的调用方式
原则下
为被装饰对象加上新功能
'''
1、函数名可以当作函数的参数
import time
def timmer(func):
#函数名可以当做函数的参数
def inner():
start = time.time()
func()
end = time.time()
print(end - start)
return inner def hahaha():
time.sleep(0.1)
print('aaaa') hahaha() 输出结果
aaaa
2、假如我们不能修改这个函数的调用方式,也不能修改原代码,该怎么做到呢
import time
def timmer(func):
#函数名可以当做函数的参数
def inner():
start = time.time()
func()
end = time.time()
print(end - start)
return inner def hahaha():
time.sleep(0.1)
print('aaaa') hahaha = timmer(hahaha) #timmer函数的地址给了hahaha 然后在进行调用
hahaha() aaaa
0.10033607482910156
# hahaha = timmer(hahaha) #timmer函数的地址给了hahaha
# hahaha() #实际上执行的是timmer
3、函数传参
def timmer(func): #---> hahaha
def inner(*args,**kwargs): #动态参数接收从kkk传来的1,2并进行压缩成元组
#args == (1,2) kwargs == {}
#*args == 1,2 **kwargs == a =1,b = 2
func(*args,**kwargs) # ---》kkk #func把值传给kkk并还原,实际上就是解压之前动态参数接收的压缩的值,返回给kkk函数
return inner def kkk(a,b):
print(a) kkk = timmer(kkk) #timmer函数里的func是kkk函数,然后返回inner函数给kkk
kkk(1,2) #kkk函数调用并传参给inner(动态参数*args), 1
参数
#实参:调用函数的时候传入的参数
#形参
#位置参数:必须传值
def aaa(a,b):
print(a,b)
aaa(1,2)
#默认参数:可以不传
def bbb(x=10): #默认参数 没上传参数的话用默认的参数,上传的话会用上传的参数。
print(x)
bbb() #x = 10
bbb(20) #x = 20
#动态参数
def ccc(*args):#1,2,3,4,5 #*args 会将ccc上传的参数以元组的方式存放
print(args) ccc(1,2,3,4,5)#按位置传参数
解压传参
def ccc(*args):#1,2,3,4,5
print(args) #ccc(1,2,3,4,5)#按位置传参数 t = (1,2,3,4,5)
ccc(t) # ((1, 2, 3, 4, 5),)
ccc(*t) #(1, 2, 3, 4, 5) #解压
按关键字传参
def ddd(**kwargs): #kwargs接收传参然后以字典的方式存放
print(kwargs) ddd(k = 'a',j = 'b')#按关键字传参数
打散赋值
def ccc(*args):
print('ccc:',args) #(1,2,3,4,5)
def inner(a,b,c,d,e):
print('inner',a,b,c,d,e)
inner(*args) #*(1,2,3,4,5) 打散 def inner(a,b,c,d,e): #接收解压的参数然后一一赋值
print('inner',a,b,c,d,e)
ccc(1,2,3,4,5)
inner(1,2,3,4,5)
4、语法糖
def timmer(func): #---> jjj
def inner(*args,**kwargs):
ret = func(*args,**kwargs) # --->ret = jjj()
print(ret)
return ret
return inner @timmer #jjj = timmer(jjj) 语法糖
def jjj():
return 123 jjj() #ret = jjj() 输出结果
123
5、装饰器函数
#装饰器的本质 :闭包函数
#功能:就是在不改变原函数调用方式的情况下,在这个函数前后加上扩展功能
def timmer(func):
def inner(*args,**kwargs):
'''添加函数调用之前的扩展代码'''
ret = func(*args,**kwargs)
'''添加函数调用之后的扩展代码'''
return ret
return inner
#设计模式 原则 开放封闭原则
#对扩展是开放的
#对修改是封闭的
6、装饰器装饰两个函数
def wrapper(func):#装饰
def inner(*args,**kwargs): ret = func(*args,**kwargs) return ret
return inner @wrapper #aaa = wrapper(aaa)
def aaa():
print('asghksdlhf') @wrapper #bbb = wrapper(bbb)
def bbb():
print('asghksdlhf') aaa()
bbb() #输出结果:
#asghksdlhf
#asghksdlhf
7、有参装饰器
import time def auth(auth_type): #auth_type='mysql'
def auth2(func):
def inner(*args,**kwargs):
if auth_type == 'file':
name=input('name:>> ')
pwd=input('password:>> ')
if name == 'egon' and pwd == '':
res=func(*args,**kwargs)
return res
else:
print('auth error')
elif auth_type == 'mysql':
print('mysql auth')
else:
print('not valid auth source')
return inner
return auth2 @auth(auth_type='mysql') #@auth2 #index=auth2(最原始的index) #index=inner
def index(name):
time.sleep(3)
print('welcome %s to index' %name) index('egon') #inner('egon')
python全栈开发从入门到放弃之装饰器函数的更多相关文章
- python全栈开发从入门到放弃之迭代器生成器
1.python中的for循环 l = [1,2,3,4,5,6] for i in l: #根据索引取值 print(i) 输出结果: 1 2 3 4 5 6 2.iterable 可迭代的 可迭 ...
- python全栈开发从入门到放弃之面向对象的三大特性
组合 class Course: def __init__(self,name,period,price): self.name = name self.period = period self.pr ...
- python全栈开发从入门到放弃之常用模块和正则
什么是模块? 常见的场景:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀. 但其实import加载的模块分为四个通用类别: 1 使用python编写的代码(.p ...
- python全栈开发从入门到放弃之模块和包
一 模块 1 什么是模块? 常见的场景:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀. 但其实import加载的模块分为四个通用类别: 1 使用python编 ...
- python全栈开发从入门到放弃之socket网络编程基础
网络编程基础 一 客户端/服务器架构 1.硬件C/S架构(打印机) 2.软件C/S架构 互联网中处处是C/S架构 如黄色网站是服务端,你的浏览器是客户端(B/S架构也是C/S架构的一种) 腾讯作为服务 ...
- python全栈开发从入门到放弃之递归函数的调用
1.递归效率低,需要在进入下一次递归时保留当前的状态,见51cto博客 解决方法是尾递归,即在函数的最后一步(而非最后一行)调用自动但是python又没有尾递归,且对递归层级做了限制 必须有一个明确的 ...
- python全栈开发从入门到放弃之初识面向对象
面向过程 VS 面向对象 面向过程的程序设计的核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西. 优点是:极大的降低了写程序的复 ...
- python全栈开发从入门到放弃之socket并发编程多进程
1.1 multiprocessing模块介绍 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在python中大部分情况需要使用多进程 ...
- python全栈开发从入门到放弃之socket并发编程多线程
一 threading模块介绍 multiprocess模块的完全模仿了threading模块的接口,二者在使用层面,有很大的相似性,因而不再详细介绍 二 开启线程的两种方式 from threadi ...
随机推荐
- 第二百七十节,Tornado框架-生成验证码图片,以及验证码结合Session验证
Tornado框架-生成验证码图片,以及验证码结合Session验证 第一.生成验证码图片 生成验证码图片需要两个必须模块 1.python自带的random(随机模块) 2.Pillow()图像处 ...
- Application应用程序级变量
对于每一个网站访问用户都要访问的变量,应该将它设为________变量.(选择1项) A. Session B. Reques C. Response D. Application 解答:D
- java------HashMap与HashSet的区别
HashMap和HashSet的区别是Java面试中最常被问到的问题.如果没有涉及到Collection框架以及多线程的面试,可以说是不完整.而Collection框架的问题不涉及到HashSet和H ...
- html的a标签的 href 和 onclick。
主要用于给超链接添加点击事件. aa.html <html> <body> <span>this si</span> </body> < ...
- angularJs多文件上传
<input type="file" id="file{{$index}}" class="file{{$index}}" ngf-s ...
- XAML 中使用空格键(空白字符)
默认情况下,XAML折叠所有空白,这意味着包含空格.tab 键以及回车的长字符串将被转换为单个空格.而且,如果在一个元素内容之前或之后添加空白,这个空格将被完全忽略. 有时这并不是所期望的结果.例如, ...
- js修改剪切板内容的方法
代码如下: //绑定在了body上,也可以绑定在其他可用元素行,但是不是所有元素都支持copy事件. $(document.body).bind({ copy: function(e) {//copy ...
- HTML-网页常见错误
400 请求出错 由于语法格式有误,服务器无法理解此请求.不作修改,客户程序就无法重复此请求. HTTP 错误 401 401.1 未授权:登录失败 此错误表明传输给服务器的证书与登录服务器所 ...
- 《C#高级编程》学习笔记----c#内存管理--栈VS堆
本文转载自Netprawn,原文英文版地址 尽管在.net framework中我们不太需要关注内存管理和垃圾回收这方面的问题,但是出于提高我们应用程序性能的目的,在我们的脑子里还是需要有这方面的意识 ...
- codevs 5964 [SDOI2017]序列计数
[题解] 官方题解就两句话. 写了三个版本的不同分值代码.看代码吧. 前导1 //f[i][j][1/0]表示长为i,sum mod p=j,是否已经选了质数的方案数 #include<cst ...