10.装饰器

一.初识

1.引入

现在有这样两个函数

def func1():
	print("这是func1")

def func2():
	print("这是func2")

我想让他俩每次执行之前先打印一下时间,就是这样

import time
def func1():
	print("这是func1")
	
def func2():
	print("这是func2")

print(time.time())
func1()
print(time.time())
func1()

但是,如果我有很多函数之前都要打印时间,一个一个写太麻烦,所以我们把打印时间这段代码封装成函数

import time
def timer():
	print(time.time)
def func1():
	timer()
	print("这是func1")
	
def func2():
	timer()
	print("这是func2")

问题又来了,我不想动我原来的代码,而且我也不想改变我调用函数的方式,我就是想给他加这个打印时间的功能。我们考虑可以用闭包搞一下

import time
def timer(func):
	def inner():
		print(timer)
		func()
	return inner

def func1():
	print("这是func1")
	
def func2():
	print("这是func2")

#使用:
func1 = timer(func1)
func1()  #这样搞的话,表面上看起来原函数代码没变,而且调用方式也没变

其实,不知不觉我们已经把装饰器给整出来了。
装饰器的作用就是:不改变原来函数的代码和调用方式,额外增加新的功能
实质上是闭包的一种应用

一个基本的装饰器写法及使用:

def wrapper(func):
	def inner(*args,**kwargs):
		......    #执行函数前的操作
		ret = func()
		return ret
	return inner  #执行函数后的操作

@wrapper      #@wrapper是py的语法糖,下面再说
def func1():
	pass

2.理解

(1)理解装饰器不会改变原函数的代码和调用方式?
在这里插入图片描述
(2)为啥是@wrapper
首先了解一下语法糖是什么?
语法糖:计算机语言添加的某种语法,对计算机语言的功能没有任何影响,但是更方便程序员的使用

@wrapper是py的语法糖,py开发者规定装饰器就是这样使用的.我们只要记住这个用法就好了,但是要了解@wrapper的工作流程:
在这里插入图片描述

(3)传参问题

def wrapper(func):
	def inner():
		func(num)
	return inner  
@wrapper      
def func1(num):
	return "num"
print(func1(5))

运行结果是这样:
在这里插入图片描述
为什么会这样?因为上述代码根本没把参数传进去
上边已经分析过了,执行func1(1)—>inner(1),但是inner本身就没定义参数,硬传肯定会报错

(4)返回值问题
看一段代码

def wrapper(func):
	def inner(num):
		func(num)
	return inner 
@wrapper      
def func1(num):
	return "num"
print(func1(5))

运行结果:
在这里插入图片描述
这个问题也很常见,为什么会是None?因为我们没有接收返回值,我们接收原func1函数的返回值,就得去原func1函数执行的地方拿,也就是inner函数里。

二.进阶

1.装饰器的修复技术

def wrapper1(func):
	def inner():
		print("前")
		ret = func()
		print("后")
		return ret
	return inner
@wrapper1
def func1():
	print("这是func1")

print(func1.__name__)

结果是:inner,加了装饰器的话,原函数的名称和文档都会变,这样肯定不行,我还是想要原函数自己的东西,这就得用装饰器的修复技术

from functools import wraps
def wrapper2(func):
	@wraps(func)
	def inner():
		print("前")
		ret = func()
		print("后")
		return ret
	return inner

@wrapper2
def func2():
	pritn("这是func2")

print(func2.__name__)    #结果为func2

2.多个装饰同一个函数

def wrapper1(func):
	def inner():
		print("wrapper1前")
		func()
		print("warpper1后")
	return inner

def wrapper2(func):
	def inner():
		print("wrapper2前")
		func()
		print("wrapper2后")
	return inner

@wrapper2    
@wrapper1   
def func1():
	print("func")

func1()


运行结果:
wrapper2前
wrapper1前
func
warpper1后
wrapper2后

其实也不难,慢慢捋一捋
在这里插入图片描述
在这里插入图片描述

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值