Python可以通过装饰器的入参指定装饰函数或方法的位置参数的有效范围,并且进行验证。
描述
装饰器入参接收要验证的参数的位置及参数的有效范围,通过位置获取参数实际值,通过范围对参数实际值进行判断验证。
(1) 最外层定义装饰器rangetest,入参argchecks保存装饰器入参,返回可调用对象onDecorator-次外层;
(2) 次外层定义onDecorator,入参func保存装饰函数或方法,返回可调用对;
(3) 最内层定义onCall,入参args保存装饰函数或方法的入参,返回调用结果;
(4) 入参argchecks为位置参数列表,第1个为装饰函数或方法的参数位置,第2和3个为装饰函数或方法的参数最小值和最大值;
(5) 入参args接收装饰函数或方法的入参,根据argchecks的第1个变量ix的值,获取需要验证的入参的位置,通过args[ix]获取位置入参的实际值,将其与argchecks的第2和第3个值进行比较,验证是否在有效范围。
示例
>>> def rangetest(*argchecks):
#argchecks 位置参数列表,每个列表第1位需与函数入参位置对应
def onDecorator(func):#接收函数或方法
if not __debug__:#内置变量,默认True
return func
else:
def onCall(*args):#函数或方法入参列表
for (ix,low,high) in argchecks:
# ix 与需验证的入参位置对应
if args[ix]<low or args[ix]>high:
errmsg='入参 %s 不在 [%s,%s] 范围内'%(args[ix],low,high)
raise ValueError(errmsg)
return func(*args)
return onCall
return onDecorator
>>> def exDecorator(func):
def onCall(*args):
try:
return func(*args)
except ValueError as ve:
print(ve)
return onCall
描述
通过装饰器第1个入参指定需要验证函数的入参位置。2和3入参指定有效范围。
@rangetest**((1,0,120))的1表示persinfo(name,age)**函数要验证的入参位置为1即age入参,0,120表示,age的有效范围为[0,120]。
示例
>>> @exDecorator
@rangetest((1,0,120))#1 表示验证persinfo索引为1的入参age的范围
def persinfo(name,age):
print('%s 今年 %s 岁' %(name,age))
>>> @exDecorator
@rangetest((0,0,2999),(1,1,12),(2,1,31))#对Y,M,D都验证
def birthday(Y,M,D):
print('生日={0}年{1}月{2}日'.format(Y,M,D))
>>> persinfo('梯阅线条',36)
梯阅线条 今年 36 岁
>>> persinfo('梯阅线条',121)
入参 121 不在 [0,120] 范围内
>>> birthday(2023,10,21)
生日=2023年10月21日
>>> birthday(3023,10,21)
入参 3023 不在 [0,2999] 范围内
>>> birthday(2023,13,21)
入参 13 不在 [1,12] 范围内
>>> birthday(2023,12,51)
入参 51 不在 [1,31] 范围内
描述
通过装饰器第1个入参指定需要验证方法的入参位置。2和3入参指定有效范围。
@rangetest**((1,0.0,1.0))的1表示giveRaise(self,percent)**函数要验证的入参位置为1即percent入参,0.0,1.0表示,percent的有效范围为[0.0,1.0]。
示例
>>> class Person:
def __init__(self,name,job,pay):
self.job=job
self.pay=pay
@exDecorator
@rangetest((1,0.0,1.0))
def giveRaise(self,percent):
self.pay=int(self.pay*(1+percent))
>>> p1=Person('梯阅线条','自由职业',500000)
>>> p1.giveRaise(0.2)
>>> p1.pay
600000
>>> p1.giveRaise(1.2)
入参 1.2 不在 [0.0,1.0] 范围内