构造函数的装饰器验证,Python
Decorator Validation for Constructor, Python
我想验证用户是否使用装饰器正确初始化了以下测试 class。这是我第一次使用装饰器,因此我对它们有点不确定。验证标准是所有整数必须小于 11,但可能有一些字符串或其他参数,if 语句可能会失败。由于 for 循环,必须首先传递“关键”参数 (int)。否则 TypeError 异常将 return func。
这就是我到目前为止得到的结果,但我对此并不满意:
def validate_max(func):
"""Decorator to validate a function passed as argument.
Args:
func (function): Function to validate.
"""
def wrapper(*args, **kwargs):
# throw away the first argument, because it will be the instance itself
arguments = [arg for arg in args if args.index(arg) != 0]
for arg in arguments:
# try statement, because you may expect a str as one constructor argument
try:
if arg > 10:
raise ValueError("One or more arguments are higher than 10")
except TypeError:
return func(*args, **kwargs)
return wrapper
class Test:
@validate_max
def __init__(self, x, y, name):
"""Constructor of Test class
Args:
x (int): An integer.
y (int): An integer.
name (str): A string.
"""
self.x = x
self.y = y
self.name = name
if __name__ == "__main__":
t = Test(1, 20, "hi")
如果您看到其他您会以不同方式处理的内容,请现在告诉我。
现在您在遇到第一个 non-int 参数后调用该函数。听起来你只想检查int,其他类型基本不关心。仅当所有参数不是整数或小于 11 时,才调用函数:
from itertools import chain
def validate_max(func):
def wrapper(*args, **kwargs):
for arg in chain(args, kwargs.values()):
# try statement, because you may expect a str as one constructor argument
try:
if arg > 10:
raise ValueError("One or more arguments are higher than 10")
except TypeError:
pass
return func(*args, **kwargs)
return wrapper
按照描述的更紧凑的版本可以是:
def validate_max(func):
def wrapper(*args, **kwargs):
if all(arg <= 10 for arg in chain(args, kwargs.values()) if isinstance(arg, int)):
return func(*args, **kwargs)
raise ValueError("One or more arguments are higher than 10")
return wrapper
我不确定你的问题是什么。
如果您要求这种验证的最佳实践,那么我建议您在此处删除装饰器并使用 pydantic 进行类型验证。
您可以声明一个架构 class 如下:
from pydantic import BaseModel,
class Coordinates(BaseModel):
x: int = Field(...,lt=11)
y: int = Field(...,lt=11)
class Test:
def __init__(self, coor = Coordinates, name: str):
self.x = coor.x
self.y = coor.y
self.name = name
我想验证用户是否使用装饰器正确初始化了以下测试 class。这是我第一次使用装饰器,因此我对它们有点不确定。验证标准是所有整数必须小于 11,但可能有一些字符串或其他参数,if 语句可能会失败。由于 for 循环,必须首先传递“关键”参数 (int)。否则 TypeError 异常将 return func。 这就是我到目前为止得到的结果,但我对此并不满意:
def validate_max(func):
"""Decorator to validate a function passed as argument.
Args:
func (function): Function to validate.
"""
def wrapper(*args, **kwargs):
# throw away the first argument, because it will be the instance itself
arguments = [arg for arg in args if args.index(arg) != 0]
for arg in arguments:
# try statement, because you may expect a str as one constructor argument
try:
if arg > 10:
raise ValueError("One or more arguments are higher than 10")
except TypeError:
return func(*args, **kwargs)
return wrapper
class Test:
@validate_max
def __init__(self, x, y, name):
"""Constructor of Test class
Args:
x (int): An integer.
y (int): An integer.
name (str): A string.
"""
self.x = x
self.y = y
self.name = name
if __name__ == "__main__":
t = Test(1, 20, "hi")
如果您看到其他您会以不同方式处理的内容,请现在告诉我。
现在您在遇到第一个 non-int 参数后调用该函数。听起来你只想检查int,其他类型基本不关心。仅当所有参数不是整数或小于 11 时,才调用函数:
from itertools import chain
def validate_max(func):
def wrapper(*args, **kwargs):
for arg in chain(args, kwargs.values()):
# try statement, because you may expect a str as one constructor argument
try:
if arg > 10:
raise ValueError("One or more arguments are higher than 10")
except TypeError:
pass
return func(*args, **kwargs)
return wrapper
按照描述的更紧凑的版本可以是:
def validate_max(func):
def wrapper(*args, **kwargs):
if all(arg <= 10 for arg in chain(args, kwargs.values()) if isinstance(arg, int)):
return func(*args, **kwargs)
raise ValueError("One or more arguments are higher than 10")
return wrapper
我不确定你的问题是什么。 如果您要求这种验证的最佳实践,那么我建议您在此处删除装饰器并使用 pydantic 进行类型验证。 您可以声明一个架构 class 如下:
from pydantic import BaseModel,
class Coordinates(BaseModel):
x: int = Field(...,lt=11)
y: int = Field(...,lt=11)
class Test:
def __init__(self, coor = Coordinates, name: str):
self.x = coor.x
self.y = coor.y
self.name = name