构造函数的装饰器验证,Python

问题描述

我想验证用户是否通过使用装饰器正确地初始化了以下Test类。这是我第一次使用装饰器,因此我对它们有点不确定。验证标准是所有整数必须小于11,但是可能会有一些字符串或其他参数,其中if语句可能会失败。由于for循环,必须首先传递“关键”参数(int)。否则,TypeError异常将返回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")

如果您发现其他地方会有所不同,请现在让我来。

解决方法

现在,您在遇到第一个非整数参数之后调用该函数。听起来您只想检查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中使用类型验证。 您可以按照以下方式声明架构类:

$cart_item['data']->set_price($cart_item['data']->price / $conversion_rate);