python装饰器学习以及使用方法

装饰器定义

装饰器原理

1、提出问题

def foo():
	print('foo')
	pass
#foo 表示的是函数
#foo() 表示的是执行foo函数
def foo():
	print('foo')
foo = lambda x:x+1
foo()
#此时执行的是lambda表达式,而不是原来的foo函数,因为foo这个名字被重新指向了另外的一个匿名函数

在这里插入图片描述
在代码里面重名函数会覆盖后面的函数会覆盖前面定义的函数,导致原来定义的函数丢失,出现错误
2、实际问题
写代码要遵循开放封闭原则,虽然这个原则是用于面向对象开发的,但是也适用于函数式编程,简单来说,它规定已经实现功能代码是不允许修改的,但是可以被扩展。
TODO-封闭:已经实现的功能代码块
TODO-开放: 对扩展开放
伪代码 :

def w1(func):
	def inner():
		#添加的功能一
		#添加的功能二
		#添加的功能三
		func()
	return inner


@w1
#语法糖
def f1():
	print('f1')
@w1

def f2():
	print('f2')
#此时w1作为额外的功能就被添加到各个需要添加的函数上了

对于上述代码,也是仅仅对基础平台代码进行修改,就可以实现在其他人调用函数f1,f2之前进行添加功能操作
实际的装饰器代码

def w1(func):
	def inner():
		print('正在验证权限')
		func()#是为了在导入不同函数时,不发生冲突
	return inner
def f1():
	print('---f1---')
def f2():
	print('---f2---')
#innerFunction =w1(f1)
#innerFunction()
#但是此时使用的函数是innerFunction()不是原来的f1(),f2(),相当于改变了函数的调用方式
f1 =w1(f1)
f1()
#此时使用的是闭包对函数进行装饰,并且函数的调用方式未发生改变

先计算等号右边_注意!

两个装饰器

demo:

#定义函数完成包裹数据
def makeBold(fn):
	def wrapped():
		return "<b>"+fn()+"</b>"
	return wrapped
#定义函数完成包裹数据
def makeItalic(fn):
	def wrapped():
		return "<i>"+fn()+"</i>"
	return wrapped
@makeBold
def test():
	return "hello world__1"
@makeItalic
def test2():
	return "hello world__2"
@makeBold
@makeItalic
def test3():
	return 'hello world__3'
#在最后一个函数里面有两个装饰器
ret = test3()
print(test1())
print(test2())
print(test3())
print(ret)
#此时显示的是装饰顺序

在这里插入图片描述其中makeBold先装饰的是下面的makeItalictest函数在装饰这两个的时候将先运行下面的程序,即:

@makeItalic
def test3():
	print('---3---')
	return 'hello world'
ret = test3()
print(ret)

此时装饰器makeBold需要一个装饰一个函数,但是在此装饰器后面是另一个装饰器makeItalic在运行完这个装饰器后,才是一个函数,所以装饰器makeItalic会先运行,之后再由前面的装饰器装饰。

装饰器什么时候进行装饰

CODE:

def w1(func):
	print('---正在装饰---')
	def inner():
		print('---正在验证权限---')
		func()
	return inner
#只要python解释器执行到了这个代码,那就会自动的进行装饰,而不是等到调用的时候才装饰
@w1
def f1():
	print('---f1---')
#在调用函数之前,f1已经装饰完成
f1()

装饰器执行时间

第一个装饰器装饰前:
在这里插入图片描述装饰器装饰后,传递的是装饰后的函数,给上一个装饰器
在这里插入图片描述

装饰器对有参数,无参数函数进行装饰

无参数函数
例子

from time import ctime,sleep
def timefun(func):
	def wrappedfunc():
		print('%s called at %s'%(func,__name__,ctime())
		func()
	return wrappedfunc
@timefun
def foo():
	print("i am foo")
foo()
sleep(2)
foo()

两个参数函数

def func(functionName):
	print('---func---1---')
	def func_in(aa,bb):
	#如果不写出来形参,就会导致后面的调用失败这里不写参数就会导致,实际装饰多参数的函数时,实参传不进来
		print('---func_in---1---')
		functionName(aa,bb)#此时的functionName是表示的后面被装饰的函数,如果不加实参在调用时,就会错误
		#如果没有aa,bb当作实参传递就会导致最后调用失败
		print('---func_in---2---')
	print('---func---2')
	return func_in
@func
def test(a,b):
	print('---test-a=%,b =%d---'%(a,b))
test(1122)

多参数函数装饰

def func(functionName):
	print('---func---1---')
	def func_in(*args,**kwargs):
	#此时args是以 元组 保存,kwargs是以字典保存
		print('---func_in---1---')
		functionName(*args,**kwargs)#此时的functionName是表示的后面被装饰的函数,如果不加实参在调用时,就会错误
		#如果没有aa,bb当作实参传递就会导致最后调用失败
		print('---func_in---2---')
	print('---func---2')
	return func_in
@func
def test(a,b):
	print('---test-a=%,b =%d---'%(a,b))
test(1122)
#当传递的实参数量不定时,可以设置多变量,如上所示,此时装饰的函数的实参数量不受限制

使用装饰器对有返回值的函数进行装饰

def func(functionName):
	print('---func---1---')
	def func_in(*args,**kwargs):
		print('func_in_begging')
		functionName(*args,**args)
		print('end of the func_in')
	print('decoration is over')
	return func_in
@func
def test():
	print('what is your name')
	return  'haha'
ret = test()
print('test return value is %s'%ret)
#此时打印的值是空值None理由如下

在这里插入图片描述在装饰后,test现在指向的是func_in()函数,在后面对ret进行赋值,ret =test()时,赋值的是func_in这个函数,而func_in这个函数没有返回值,所以在输出的时候是None,

def func(functionName):
	print('---func---1---')
	def func_in(*args,**kwargs):
		print('func_in_begging')
		v= functionName(*args,**args)
		#此时的functionName接受到的值就是装饰的函数test返回的值,所以将这个值保存,并返回。
		print('end of the func_in')
		return  v
	print('decoration is over')
	return func_in
@func
def test():
	print('what is your name')
	return  'haha'
ret = test()#此时接受到的值才是真的需要返回的值
print('test return value is %s'%ret)
#此时打印的值是空值None理由如下

通用的装饰器

式例模板

#通用的装饰器
#第一步:闭包
def w1(functionName):
	def w1_in(*args,**kwargs):
	#函数测试
		return_key=functionName(*args,**kwargs)
		return return_key
	return w1_in
@w1
def test():
	print('test')
@w1
def test1():
	print('test1')
	return '测试'
@w1
def test2(a,b,c):
	print(a,b,c)
			

带有参数的装饰器

在这里插入图片描述OS:这个代码实在是懒得再写一遍了

装饰器结束了!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值