什么是装饰器
#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. jQuery对象与javaScript对象的互换

    1. jQuery对象-->Dom对象 1) 通过 .[0] 的方式:       var $s = $(.class);  (jQuery对象)       var s = $s.[0];   ...

  2. MathType中怎么设置字体默认颜色

    MathType功能非常强大,在编辑公式时使用非常方便.利用MathType破解版不仅可以改变公式的字体和字号,也可以改变公式字体颜色.有时在编辑完成后需要对MathType公式格式全部进行修改,这时 ...

  3. error C2678: 二进制“+”: 没有找到接受“const char [22]”类型的左操作数的运算符(或没有可接受的转换)没有与这些操作数匹配的“+”运算符

    错误:没有与这些操作数匹配的“+”运算符,操作数类型为const char [20]+CString 分析原因:其提示操作数类型为const char [20]+CString 可见是类型有问题 故加 ...

  4. C++之运行时类型识别RTTI

     C++ Code  12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849 ...

  5. WPF 附加事件

    在WPF中有许多控件有他们自己的特殊的事件.按钮就是一个例子——它添加了 Click 事件,而其他任何类都没有定义该事件. 这回导致两难的境地.假设在 StackPanel 面板中包装了一堆按钮,并且 ...

  6. 【BZOJ1116】[POI2008]CLO 并查集

    [BZOJ1116][POI2008]CLO Description Byteotia城市有n个 towns m条双向roads. 每条 road 连接 两个不同的 towns ,没有重复的road. ...

  7. if...else if...else和switch语句的注意点

    java if...else if...else 语句 if 语句后面可以跟 elseif…else 语句,这种语句可以检测到多种可能的情况. 使用 if,else if,else 语句的时候,需要注 ...

  8. MongoDB插入多条数据

    刚开始学mongodb,只知道几个命令,insert插入也只能一条一条插入,而在实际情况下数据一般都非常多,刚开始想直接上传json文件,网上搜了n多方法发现这种方法不好弄,然后就想着要么一下子把多条 ...

  9. iOS如何让主界面不显示NavigationBar

    这个问题曾经困扰过我.现在我给出正解.- (void)viewWillAppear:(BOOL)animated {    [super viewWillAppear:animated]; [self ...

  10. getResource()和getResourceAsStream以及路径问题(转)

    用JAVA获取文件,听似简单,但对于很多像我这样的新人来说,还是掌握颇浅,用起来感觉颇深,大常最经常用的,就是用JAVA的File类,如要取得c:/test.txt文件,就会这样用File file ...