当前位置:   article > 正文

python装饰器学习以及使用方法_def w1(): print('正在装饰') def inner(): print('正在验证权限

def w1(): print('正在装饰') def inner(): print('正在验证权限') return inner(

装饰器定义

装饰器原理

1、提出问题

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

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

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


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

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

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

对于上述代码,也是仅仅对基础平台代码进行修改,就可以实现在其他人调用函数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()
#此时使用的是闭包对函数进行装饰,并且函数的调用方式未发生改变

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

先计算等号右边_注意!

两个装饰器

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)
#此时显示的是装饰顺序
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

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

@makeItalic
def test3():
	print('---3---')
	return 'hello world'
ret = test3()
print(ret)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

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

装饰器什么时候进行装饰

CODE:

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

装饰器执行时间

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

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

无参数函数
例子

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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

两个参数函数

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)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

多参数函数装饰

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)
#当传递的实参数量不定时,可以设置多变量,如上所示,此时装饰的函数的实参数量不受限制
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

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

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理由如下

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

在这里插入图片描述在装饰后,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理由如下
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

通用的装饰器

式例模板

#通用的装饰器
#第一步:闭包
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)
			
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

带有参数的装饰器

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

装饰器结束了!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/213296?site
推荐阅读
相关标签
  

闽ICP备14008679号