Python装饰器


装饰器:为原函数去扩展新功能,用新函数去替换旧函数
作用:在不改变原代码的前提下,实现功能性扩展
符号(语法糖):@

一、装饰器的基本用法

先来看下面这段代码:

def extend(func):
	def newfunc():
		print("I have a pen")
		func()
	return newfunc
def func():
	print("I have an apple")
func=extend(func)
func()

运行结果:
运行结果

在上图中,使用闭包函数扩展了函数func的功能

@语法糖的使用:
1、可以自动把@下面的函数当成参数传递给装饰器
2、把新函数返回,让新函数替换旧函数,以实现功能上的扩展(基于原函数)

def extend(func):
	def newfunc():
		print("I have a pen")
		func()
	return newfunc
@extend
def func():
	print("I have an apple")
func()

运行结果:
运行结果

二、装饰器的嵌套

def extend1(func):
	def newfunc1():
		print("扩展start1")
		func()
		print("扩展end1")
	return newfunc1
def extend2(func):
	def newfunc2():
		print("扩展start2")
		func()
		print("扩展end2")
	return newfunc2
@extend2
@extend1
def func():
	print("我是func函数")
func()

运行结果:
运行结果

在上例中,首先将func传入extend1装饰器进行扩展,再将扩展后的函数覆盖原func,最后将新生成的函数传入装饰器extend2,得到最后结果。

三、用装饰器扩展带有参数的原函数

def extend(func):
	def newfunc(who,where,do):
		print("8月7日")
		func(who,where,do)
		print("end")
	return newfunc
@extend #func=extend(func)
def func(who,where,do):
	print("{}在{}{}".format(who,where,do))
func("Lsir","电影院","看电影")

运行结果:
运行结果

四、用装饰器扩展带有参数和返回值的原函数

def extend(func):
	#形参打包
	def new_func(*args,**kwargs):
		print("hobby:")
		#实参解包
		lst=func(*args,**kwargs)
		print(lst)
		print("end")
	return new_func
@extend
def func(*args,**kwargs):
	strvar=""
	for n in kwargs:
		strvar += kwargs[n]
	for i in args:
		strvar += i
	return strvar
func("Lsir","在电影院","看电影",date="8月7日")

运行结果:
运行结果

五、用类装饰器来拓展原函数

class MyClass():
	def __call__(self,func):
		return self.extend(func)
	def extend(self,func):
		def newfunc():
			print("落华却看悲白发")
			func()
		return newfunc
@MyClass() #func=obj(func)
def func():
	print("少时不识曲中天")
func()

运行结果:
运行结果

@MyClass() 生成对象,相当于@obj,func=obj(func),触发call魔术方法,func传入MyClass类中,执行extend函数,return返回值覆盖func,func()实际执行newfunc().

六、带有参数的函数装饰器

def outer(num):
	def extend(func):
		def newfunc1(self):
			print("8月5日")
			func(self)
		def newfunc2(self):
			print("8月6日")
			func(self)
		def newfunc3(self):
			print("8月7日")
			func(self)
		if num == 1:
			return newfunc1
		elif num == 2:
			return newfunc2
		elif num == 3:
			return newfunc3
	return extend
class MyClass():
	@outer(1)
	def func1(self):
		print("Lsir在电影院")
	@outer(2)
	def func2(self):
		print("Lsir在机场")
	@outer(3)
	def func3(self):
		print("Lsir在公司")
obj=MyClass()
obj.func1()
obj.func2()
obj.func3()

运行结果:
运行结果

七、带有参数的类装饰器

class Extend():
	car="特斯拉"
	def __init__(self,num):
		self.num=num
	def __call__(self,cls):
		if self.num == 1:
			return self.moudle1(cls)
		elif self.num == 2:
			return self.moudle2(cls)
	def oil(self):
		print("油耗3.0")
	def moudle1(self,cls):
		def newfunc():
			cls.car=Extend.car
			cls.oil=Extend.oil
			return cls()
		return newfunc
	def moudle2(self,cls):
		def newfunc():
			if "func" in cls.__dict__:
				res=cls.func(self)
				cls.func=res
				return cls()
		return newfunc
@Extend(1)
class MyClass():
	def func(self):
		return "时速百公里"
obj = MyClass()
print(obj.car)
obj.oil()

@Extend(2)
class MyClass():
	def func(self):
		return "时速百公里"

obj = MyClass()
print(obj.func)

运行结果:
运行结果

分析:
以参数1为例
参数为1,代码解析:
@Extend(1) => @obj => @符第一次发动技能:
把MyClass当成参数传递给obj => obj(MyClass) => return self.moudle1(cls) => return newfunc
@obj => @符第二次发动技能:
实现替换效果,将 MyClass = newfunc

obj = MyClass() = newfunc() = cls() = 对象
对象.属性 obj.car
对象.方法 obj.oil()

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值