首页 > 编程语言 >python装饰器

python装饰器

时间:2023-01-09 00:22:05浏览次数:46  
标签:index python wrapper func time print 装饰 def

python装饰器--开放封闭原则

知识点回顾

# *args **kwargs
def wrapper(*args,**kwargs): # 接受(形参) args=(1,2,3) kwargs={'a':1,'b':2}
    index(*args,**kwargs)	# 打散(实参)
    						# index(*(1,2,3),**{'a':1,'b':2})
        					# index(1,2,3,a=1,b=2) 原封不动的传给index
wrapper(1,2,3,a=1,b=2)

1 ----> 5装饰器无参

6 ----> 7装饰器有参

1. 原函数无参的装饰

在不改变原代码上,添加新的功能

装饰器需要定义在原函数前面,并且命名要明确

import time

'''装饰函数'''
def timmer(func):		# 1.传入函数名
    def wrapper()
    	start = time.time()
    	func()			# 2.执行传入函数
    	end = time.time()
    	print(start - end)
    retrun wrapper  	# 3.返回了函数名
    
'''原来代码'''
def index():
    time.sleep(3)
    print('index无参数')
    
'''index旧瓶新装'''    
index = timmer(index) 	# 4.等于把旧index传入到wrapper函数中了
						# 4-1 新的index = warpper内存地址
index() 				# 5.新的index,其实调用-->wrapper()

1.1 语法糖

​ 语法糖:让你开心的事

import time

def timmer(func):
    def wrapper()
    	start = time.time()
    	func()
    	end = time.time()
    	print(start - end)
    retrun wrapper

@timmer				# 1.语法糖其实是封装了上面[4]的写法,使其更加直观->@装饰器名
def index():
    time.sleep(3)
    print('index无参数')
    
index()				# 2.新的index,其实调用-->wrapper()

2. 原函数有参的装饰器

import time

def timmer(func):
    def wrapper(*args,**kwargs) # 1.传入不确定参数
    	start = time.time()
    	func(*args,**kwargs)	# 2.把参数传给原函数(⚠️一定要带 * 号)
    	end = time.time()
    	print(start - end)
    retrun wrapper

@timmer
def index(x,y):
    time.sleep(3)
    print('index %S %S' % (x,y))
    
index(1,2)

3.原函数有返回值的装饰器

import time

def timmer(func):
    def wrapper(*args,**kwargs)
    	start = time.time()
    	res =func(*args,**kwargs)	# 2.res接受原函数返回值
    	end = time.time()
    	print(start - end)
    	return res					# 3.在装饰器末尾加上return res
    retrun wrapper

@timmer
def index(x,y):
    time.sleep(3)
    return x + y					# 1.原函数有返回值
    
res = index(1,2)					# 4.通过装饰器后拿到了返回值

4.原函数执行多个装饰器执行

多个装饰器是从底下向上运行的

def wrapper1(func):
    def inner1(*args, **kwargs):
        print("wrapper1 装饰函数前 可以做一些事 ")
        ret = func(*args, **kwargs)
        print("wrapper1 装饰函数后 可以做一些事 ")
        return ret
    return inner1

def wrapper2(func):
    def inner2(*args, **kwargs):
        print("wrapper2 装饰函数前 可以做一些事 ")
        ret = func(*args, **kwargs)
        print("wrapper2 装饰函数前 可以做一些事 ")
        return ret
    return inner2

@wrapper2		# 2.
@wrapper1		# 1. 
def func():
    print("我是函数,我被两个装饰器装饰")
    return "函数 返回值"

ret = func()
print(ret)
# ----------------------------运行结果------------------------
# wrapper2 装饰函数前 可以做一些事
# wrapper1 装饰函数前 可以做一些事
# 我是函数,我被两个装饰器装饰
# wrapper1 装饰函数后 可以做一些事
# wrapper2 装饰函数前 可以做一些事
# 函数 返回值

5.伪装的更像原函数

def timmer(func):
    def wrapper(*args,**kwargs)
    	res =func(*args,**kwargs)
    	return res
    	wrapper.__name__ = func.__name__ 	# 3.需要把原函数的内置属性赋值过来
        wrapper.__doc__ = func.__doc__		# 4.不可能一个个的写完
        ......
    retrun wrapper

@timmer
def index(x,y):
    '''这是一个文档'''
    print(x,y)
    
print(index.__name__)  ---->index			# 1.伪装原函数
print(index.__doc__)---->这是一个文档

5-1. from functools import wraps

⚠️⚠️⚠️一定要记住:wraps(func)

from functools import wraps					# 1.wrpas(func)就是装饰器

def timmer(func):
    @wraps(func)							# 2.就是将原函数的内置属性拿过来
    def wrapper(*args,**kwargs)
    	res =func(*args,**kwargs)
    	return res
    retrun wrapper

@timmer
def index(x,y):
    '''这是一个文档'''
    print(x,y)
    
print(index.__name__)	---->index
print(index.__doc__)	---->这是一个文档

6.了解装饰器@作用---为7做铺垫

@名字 --> home = 名字(home)
def home():
    pass

@名字()--> 先执行名字(),返回值---> home = 返回值(home)
def home():
    pass

7.有参的装饰器(需要掌握)

  • 装饰器其实用的wrapper函数
  • 因为deco和wrapper中不能传入参数了
  • 所有外面在套一层auth
def auth(a_type):					# 1.外层在包一层函数,接受参数
  def deco(func):
    def wrapper(*args,**kwargs):
      if a_type == xxx1:				# 2,接受的参数来判断运行那个代码
        res =func(*args,**kwargs)
        return res
      elif a_type == XXX2:
        res =func(*args,**kwargs)
        return res
      elif a_type == XXX3:
        res =func(*args,**kwargs)
        return res
       else:
        print('a_type类型错误')
    return wrapper
  return deco								# 3.返回函数deco

@auth(XXX1)									# 4.使用语法糖添加类型【可变的】
def index1(x,y):
  print(x+y)
    
@auth(XXX2)		# 5.@名字()--> 先执行名字(),返回值deco-->[因为【3】return deoc]
def index2(x,y):
  print(x+y)
    
@auth(XXX3)	# 6.返回值已经是deco,再执行@deco,此时参数已经被传入内部了
def index3(x,y):
  print(x+y)

标签:index,python,wrapper,func,time,print,装饰,def
From: https://www.cnblogs.com/lxd670/p/17035818.html

相关文章

  • Python 中的生成器实现原理
    1.如何生成一个巨大的序列1.1需求描述要求生成一个包含很多元素的序列,假设:存储1个整数需要4个字节现在要创建一个包含1G个整数的序列,从0到1*1024*1024*......
  • 数据结构与算法Python版之北大慕课笔记(一)
    数据结构与算法Python版之北大慕课笔记(一)一、“变位词”判断问题1.解法一:逐字检查2.解法二:排序比较3.解法三:计数比较二、线性结构linearstructure1.四个......
  • python 每天一个知识点 第三天
    字典dict一,字典是什么?字典是Python中比较常用的数据结构,字典中每个成员是以“键:值”对的形式存放具有映射关系的数据。语法:字典以大括号“{}”包围的以“键:值”对......
  • Python 实现栈与队列
    栈栈(stack),有些地方称为堆栈,是一种容器,可存入数据元素、访问元素、删除元素,它的特点在于只能允许在容器的一端(称为栈顶端指标,英语:top)进行加入数据(英语:push)和输出数据(英语:po......
  • VsCode新建Java、SpringBoot、Python、JavaWeb项目的基本步骤
    新建Java项目选中正上方的搜索框,按下F1快捷键,输入createJava,即可出现这样的一个命令:选中这个:然后为新创建的项目选择一个合适的位置就好啦!新建SpringBoot项目选中......
  • python常用命令
    使用pip-review库(推荐)安装库pipinstallpip-review检查是否有需要更新的包>pip-reviewscikit-learn==0.23.2isavailable(youhave0.23.1)scipy==1.5.4isavail......
  • [oeasy]python0041_teletype历史_博多码_shift_capslock_字符数字切换_gear
    teletypewriter历史回忆上次内容上次见到了一个真的机械打字机感受到了蒸汽朋克的时代背景上上次区分了一些概念terminal终端,电脑连线最终的端点TeleTYpewr......
  • python学习-PTL图片-pillow相关代码
    #引用PTL图片fromPILimportImage#打开图片image=Image.open('./image/1.JPG')#打印图片print(image)#显示图片image.show()#打印图片的尺寸、模式、具体信......
  • python获取随机三位数是水仙花数
    #求随机三个数是水仙花数num=random.randint(100,999)hundred=num//100decade=num%100//10ones=num%10ifhundred**3+decade**3+ones**3==num:......
  • python打印乘法口诀、加法口诀、减法口诀,复制到EXCEL直接打印
    #乘法口诀forxinrange(1,10):foryinrange(1,x+1):print(f'{y}x{x}={x*y}',end='\t')print()print('\n')#加法口诀forxinrange(1,10......