什么是装饰器
#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. [css]解决iframe在ios设备上无法滚动

    原因: safari的webkit内核特性 解决方案: 在iframe外包裹一层div并另外设置其css属性为如下: -webkit-overflow-scrolling:touch; overflo ...

  2. adb server is out of date.killing的解决办法

    当把手机连接到电脑端口运行adb程序调试时,出现了下面这样的情况: 分析:出错的原因是adb的端口被其他程序的进程占领了,所以要做的就是找到并kill该进程.     工具/原料   cmd.exe. ...

  3. springmvc 发送PUT 和 DELETE 请求

    一: 发送 DELETE 或者 PUT 请求: 1.在表单中加入一个隐藏的参数: _method  , 值是 DELETE (或者PUT) <form action="springmv ...

  4. leetcode -- Best Time to Buy and Sell Stock III TODO

    Say you have an array for which the ith element is the price of a given stock on day i. Design an al ...

  5. box-sizing在什么情况下会失效

    众所周知,box-sizing是将w3c盒模型与IE盒模型相互转换的利器,但是有时候也会失效,那么在什么情况下回失效呢,MD在没设置高度的时候回失效的透透的,所以一定记得需要转换的时候设置个高度!!!

  6. [转]Mac下cocos2dx-3.2+Xcode环境配置和项目创建

    原文:http://blog.csdn.net/u012200908/article/details/38070885 这是有关环境配置的第二篇教程,第一篇讲的是win8下的环境配置.这里我们使用C+ ...

  7. Android 调用系统相机拍照保存以及调用系统相册的方法

    系统已经有的东西,如果我们没有新的需求的话,直接调用是最直接的.下面讲讲调用系统相机拍照并保存图片和如何调用系统相册的方法. 首先看看调用系统相机的核心方法: Intent camera = new ...

  8. SQL中的IF ELSE(CASE语句的使用)(转载)

    大家对IF ELSE语句可能都很熟悉,它是用来对过程进行控制的.在SQL的世界中CASE语句语句有类似的效果.下面简单的介绍CASE语句的用法.考虑下面的情况,假设有个user表,定义如下: CREA ...

  9. LeetCode 笔记系列 18 Maximal Rectangle [学以致用]

    题目: Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing all ones ...

  10. ajax请求步骤

    ajax步骤:第一步:创建xmlhttprequest对象,var xmlhttp = new XMLHttpRequest(); XMLHttpRequest对象和服务器交换数据.第二步:使用xml ...