您的位置:首页 > 编程语言 > Python开发

Python 装饰器 剖析详解

2019-10-21 21:54 169 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/storyfull/article/details/102672908

目录

基本概念

开闭原则:
对功能的扩展(开放)
对代码的修改(关闭)
def wrapper(fn):
def inner():
print("浇水")  # 增加一个新功能
fn()

return inner

def zaoren():
print("捏个泥人")
print('吹口仙气')
print('造成了!')

zaoren = wrapper(zaoren)  # 将原函数名传入,闭包操作后,还返回原函数名

# 原来的调用者执行
zaoren()  # 用了装饰器后,增添了新功能
zaoren()

有参数的装饰器

def play(username,password/*args, **kwargs):
print("开始打游戏",username,password/*args,**kwargs)

def wrapper(fn):
def inner(*args, **kwargs):
print("开挂")
fn(*args, **kwargs) #paly()
print("关闭外挂")

return inner

play = wrapper(play) #返回值paly 是inner
play("min","123")

#此时 原函数返回值 没忽视了

通用装饰器

def play(*args, **kwargs):
print("开始打游戏",*args,**kwargs)
return 123

def wrapper(fn):
def inner(*args, **kwargs):
print("开挂")
ret=fn(*args, **kwargs)
print("关闭外挂")
return ret
return inner

@wrapper #这个和自定义装饰器函数名一样,且如果要用,必须在它下面
def zaoren():
print("捏个泥人")
print('吹口仙气')
print('造成了!')

play = wrapper(play) #左边的paly 是函数名inner
print(play("min","123"))
zaoren=wrapper(zaoren)#加了@wrapper 就可以省略这句声明
zaoren()
通用装饰器写法:

# python里的动态代理

# 带有参数的装饰器:控制装饰器起不起作用

>>>应有示例:把游戏外挂关了

def wrapper_out(flag):
def wrapper(fn):
def inner(*args, **kwargs):
if flag == True:
print("开挂")
ret = fn(*args, **kwargs)
print("关闭外挂")
return ret
else:
ret = fn(*args, **kwargs)
return ret

return inner

return wrapper  # 这个是返回给外层装饰器的 然后和前面的@又构成了一个装饰器

ask = input("是否需要开外挂:")

@wrapper_out(False/ask)
def play(*args, **kwargs):  # 此时这个装饰器最终还是被 wrapper装饰着
print("开始打游戏", *args, **kwargs)
return 123

同一个函数被多个装饰器装饰



# 就近原则,离函数最近的最先被装饰,其他则在外围
# 输出结果:
我是第二层
我是第一层
我是第0层
开始装饰
iam runnig
结束装饰
第0层结束
第一层结束
第二层结束

装饰器的应用

# 用于校验,如登录状态
【装饰器用于普通函数】
function_list = ['login', 'watch_all', 'order']
flag = False

def login_verify(fn):#登录验证装饰器
global flag
def inner(*args, **kwargs):
while 1:
if flag == True:
ret = fn(*args, **kwargs)
return ret
else:
print("请先登录")
login()
return inner

def login():
while 1:
global flag
print("欢迎登陆!")
user_name = input("请输入用户名:")
pass_word = input("请输入密码:")
if user_name == "min" and pass_word == "123":
flag = True
print('登陆成功!欢迎使用')
return
else:
print('登陆失败')

@login_verify
def watch_all():
print('查看')

@login_verify
def order():
print('订单')

if __name__ == '__main__':
while True:
for i in range(len(function_list)):
print(i + 1, function_list[i])
num = int(input("请输入你要选择的功能序号:"))
if num == 1:
login()
elif num == 2:
watch_all()
elif num == 3:
order()
else:
print("请输入正确的数字!")

【面向对象里 不能用装饰器?】
class Function(object):
def __init__(self):
self.function_list = ['login', 'watch', 'order']

flag = False

def login(self):
while 1:
print("欢迎登陆!")
user_name = input("请输入用户名:")
pass_word = input("请输入密码:")
if user_name == "min" and pass_word == "123":
self.flag = True
print('登陆成功!欢迎使用')
return
else:
print('登陆失败')

def watch(self):
if self.flag==False:
self.login()
if self.flag==True:
print('查看')

def order(self):
if self.flag == False:
self.login()
if self.flag == True:
print('查看')

def run(self):
self.login()
for i in range(len(self.function_list)):
print(i + 1, self.function_list[i])
num = int(input("请选择功能"))
var = getattr(self, self.function_list[num - 1])
self.flag=False
var()

if __name__ == '__main__':
obj = Function()
obj.run()
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: