python自学笔记4 —— 装饰器
4.1 装饰器例程
4.1.1 单装饰
(0) 装饰函数
#这里定义一个总装饰函数,方便后续直接用于装饰被装饰函数
#注:后续函数必须加上该代码才能被正常装饰
import time # for time.sleep
def decorate(func):
print("正在准备装饰输入的函数")
def drawer(*args,**kwargs): # *args,**kwargs作用为扩大可输入参数范围
print("开始装饰")
#这里注意,func传入的参数应当与drawer传入参数相同,即 *args,**kwargs
func(*args,**kwargs) # 调用被装饰函数,位置随意,调用随意,仅为效果
time.sleep(2) # 仅为效果,无实际作用
print("装饰完成")
print("退出函数装饰")
return drawer
(1) 被装饰函数无参数输入
@decorate# 引入调用函数
def func_1(): # 定义被装饰函数1(无参)
print("此时装饰无参函数")
func_1() #输出被装饰后的函数
(2) 被装饰函数有一个参数输入(字符串或者数字)
@decorate
def func_2(a): # 定义被装饰函数2(有1参)
print("此时装饰参数为{0}的函数".format(a))
func_2(2) #输出被装饰后的函数
(3) 被装饰函数有两个参数输入(字符串或者数字)
@decorate# 引入调用函数
def func_3(a,b): # 定义被装饰函数3(有2参)
print("此时装饰参数为{0}和{1}的函数".format(a,b))
func_3(3,"glk") #输出被装饰后的函数
(4) 被装饰函数有一个列表参数输入
list = [1,2,3,'glk'] # 定义一个列表
@decorate
def func_4(list):# 定义被装饰函数4(有列表参数)
for i in list:
print(i,end="")
print("\n") # 换行,防止与下一个被装饰函数的输出混淆
func_4(list) #输出被装饰后的函数
(5) 被装饰函数有一个元组参数输入
tuple = (1,2,3,'好帅') # 定义一个元组
@decorate
def func_5(tuple):
for i in tuple:
print(i,end="")
print("\n") # 换行,防止与下一个被装饰函数的输出混淆
func_5(tuple) #输出被装饰后的函数
(6) 被装饰函数有一个字典参数输入
dict = {1 : 'glk' , 2 : '真的' , 3 : 6} # 定义一个字典
@decorate
def func_6(dict):
for i,j in dict.items(): # 遍历字典中的键与值
print(i,j," ",end="")
print("\n") # 换行,防止与下一个被装饰函数的输出混淆
func_6(dict)
4.1.2 多重装饰
离 被装饰函数 最近的 装饰函数 最先装饰
def decorate1(func) :
print("开始装饰1")
def drawer(*args,**kwargs):
func(*args,**kwargs)
print("装饰1完成")
return drawer
def decorate2(func) :
print("开始装饰2")
def drawer(*args,**kwargs):
func(*args,**kwargs)
print("装饰2完成")
return drawer
@decorate2
@decorate1
def func_1():
print("这里是被装饰函数")
func_1()
该代码输出为
开始装饰1
开始装饰2
这里是被装饰函数
装饰1完成
装饰2完成
输出结果分析:
- 首先由于离 def func_1(): 最近的是 @decorate1,故由decorate1最先装饰函数
- 由decorate1装饰完后,输出了“开始装饰1”,并且加载了decorate1中的drawer函数,此时drawer函数中调用的func函数是最初始的func_1(),最后传出drawer并赋值给func_1。这时,开始我们的decorate2装饰,输出了“开始装饰2”,并加载了decorate2中的drawer函数,但是,此时drawer函数中的func函数是由decorate1装饰后的func_1(),里面的内容如下
def func_1(): #此时是被decorate1装饰后
print("这里是被装饰函数")
print("装饰1完成")
- 最后,输出decorate2中的drawer并传给func_1()。此时,当我们调用func_1()时,比被decorate1装饰后多了一句“装饰2完成”的输出。
4.1.3 带参数装饰器
三点:
- 带参数装饰器是三层
- 最外层函数用于接受参数
- 里面内容与普通装饰器无区别
例程如下
def outer(a):
def decorate(func):
print("开始装饰")
def drawer(*args,**kwargs):
print("所传入参数为-->{0}".format(a))
print("正在装饰中.....")
func(*args,**kwargs)
print("完成装饰")
return drawer
return decorate
@outer("帅")
def func_1():
print("orz orz")
func_1()
输出如下
开始装饰
所传入参数为-->帅
正在装饰中.....
orz orz
完成装饰
4.2 装饰器应用
# 登陆验证支付
import time
islogin = False # 初始状态为未登录
Administrator = {'glk':'123','lzt':'456','whn':'789'} # 设置一个用户系列
def login_system():
'''登陆系统'''
global islogin
name = input("请输入用户名称: ")
key = input("请输入{0}的密码: ".format(name))
print("请稍等... ...")
time.sleep(2)
for i,j in Administrator.items():
if (name == i) and (j == key):
print("欢迎用户{0},登陆成功!".format(i))
islogin = True # 允许支付
break
else :
print("未找到相关信息,登录失败!")
islogin = False # 禁止支付
break
#定义一个装饰包,用于登录检测
def login_get(func):
'''登陆状态检测'''
def drawwer(*args,**kwargs):
login_system()
func(*args,**kwargs)
return drawwer
@login_get
def pay_system(): #支付系统
'''判断是否为登录状态'''
if islogin == True: # 此时为已登录
print("已经登录,允许支付")
money = input("请输入支付金额: ")
pay_ok = input("输入 'ok' 完成支付: ")
if pay_ok == 'ok':
time.sleep(2)
print("支付成功!当前支付金额为:{}元".format(money))
else:
print("当前未支付!")
elif islogin == False: # 此时为未登录
print("暂未登录,禁止支付")
pay_system()