什么是装饰器
#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全栈开发从入门到放弃之装饰器函数的更多相关文章

  1. 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  可迭代的 可迭 ...

  2. python全栈开发从入门到放弃之面向对象的三大特性

    组合 class Course: def __init__(self,name,period,price): self.name = name self.period = period self.pr ...

  3. python全栈开发从入门到放弃之常用模块和正则

    什么是模块? 常见的场景:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀. 但其实import加载的模块分为四个通用类别: 1 使用python编写的代码(.p ...

  4. python全栈开发从入门到放弃之模块和包

    一 模块 1 什么是模块? 常见的场景:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀. 但其实import加载的模块分为四个通用类别: 1 使用python编 ...

  5. python全栈开发从入门到放弃之socket网络编程基础

    网络编程基础 一 客户端/服务器架构 1.硬件C/S架构(打印机) 2.软件C/S架构 互联网中处处是C/S架构 如黄色网站是服务端,你的浏览器是客户端(B/S架构也是C/S架构的一种) 腾讯作为服务 ...

  6. python全栈开发从入门到放弃之递归函数的调用

    1.递归效率低,需要在进入下一次递归时保留当前的状态,见51cto博客 解决方法是尾递归,即在函数的最后一步(而非最后一行)调用自动但是python又没有尾递归,且对递归层级做了限制 必须有一个明确的 ...

  7. python全栈开发从入门到放弃之初识面向对象

    面向过程 VS 面向对象 面向过程的程序设计的核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西. 优点是:极大的降低了写程序的复 ...

  8. python全栈开发从入门到放弃之socket并发编程多进程

    1.1 multiprocessing模块介绍 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在python中大部分情况需要使用多进程 ...

  9. python全栈开发从入门到放弃之socket并发编程多线程

    一 threading模块介绍 multiprocess模块的完全模仿了threading模块的接口,二者在使用层面,有很大的相似性,因而不再详细介绍 二 开启线程的两种方式 from threadi ...

随机推荐

  1. 第二百七十节,Tornado框架-生成验证码图片,以及验证码结合Session验证

    Tornado框架-生成验证码图片,以及验证码结合Session验证 第一.生成验证码图片  生成验证码图片需要两个必须模块 1.python自带的random(随机模块) 2.Pillow()图像处 ...

  2. Application应用程序级变量

    对于每一个网站访问用户都要访问的变量,应该将它设为________变量.(选择1项) A. Session B. Reques C. Response D. Application 解答:D

  3. java------HashMap与HashSet的区别

    HashMap和HashSet的区别是Java面试中最常被问到的问题.如果没有涉及到Collection框架以及多线程的面试,可以说是不完整.而Collection框架的问题不涉及到HashSet和H ...

  4. html的a标签的 href 和 onclick。

    主要用于给超链接添加点击事件. aa.html <html> <body> <span>this si</span> </body> < ...

  5. angularJs多文件上传

    <input type="file" id="file{{$index}}" class="file{{$index}}" ngf-s ...

  6. XAML 中使用空格键(空白字符)

    默认情况下,XAML折叠所有空白,这意味着包含空格.tab 键以及回车的长字符串将被转换为单个空格.而且,如果在一个元素内容之前或之后添加空白,这个空格将被完全忽略. 有时这并不是所期望的结果.例如, ...

  7. js修改剪切板内容的方法

    代码如下: //绑定在了body上,也可以绑定在其他可用元素行,但是不是所有元素都支持copy事件. $(document.body).bind({ copy: function(e) {//copy ...

  8. HTML-网页常见错误

    400 请求出错  由于语法格式有误,服务器无法理解此请求.不作修改,客户程序就无法重复此请求.  HTTP 错误 401  401.1 未授权:登录失败  此错误表明传输给服务器的证书与登录服务器所 ...

  9. 《C#高级编程》学习笔记----c#内存管理--栈VS堆

    本文转载自Netprawn,原文英文版地址 尽管在.net framework中我们不太需要关注内存管理和垃圾回收这方面的问题,但是出于提高我们应用程序性能的目的,在我们的脑子里还是需要有这方面的意识 ...

  10. codevs 5964 [SDOI2017]序列计数

     [题解] 官方题解就两句话. 写了三个版本的不同分值代码.看代码吧. 前导1 //f[i][j][1/0]表示长为i,sum mod p=j,是否已经选了质数的方案数 #include<cst ...