构造函数的装饰器验证,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