简体   繁体   English

带有额外参数的python-attrs中的自定义验证器

[英]Custom validator in python-attrs with extra parameters

I have several classes defined using attrs like this one:我有几个使用 attrs 定义的类,如下所示:

from attr import attrs, attrib, validators

@attrs
class MyClass:
    name = attrib(])
    @name.validator
    def check_length(self, attribute, value):
        if not (3 <= len(value) <= 30):
            raise ValueError("Name must be between 3 and 30 characters")

    description = attrib()
    @description.validator
    def check_length(self, attribute, value):
        if not (10 <= len(value) <= 400):
            raise ValueError("Description must be between 10 and 400 characters")

For several attributes I need to create a validator to check wether the data it's in some range.对于几个属性,我需要创建一个验证器来检查数据是否在某个范围内。 I want to avoid repetition, so I can create a custom validator where I pass some extra arguments for min and max, like this one:我想避免重复,所以我可以创建一个自定义验证器,在其中为 min 和 max 传递一些额外的参数,如下所示:

def range_validator(instance, attribute, value, min_value, max_value):
    if  min_value >= len(value) >= max_value:
        raise ValueError("Must be between {} and {}".format(min_value, max_value))

But then I don't know how to call this validator from inside attrib() passing the extra args (min_value and max_value), I mean do something like:但是后来我不知道如何从传递额外参数(min_value 和 max_value)的 attrib() 内部调用此验证器,我的意思是执行以下操作:

name = attrib(validator=[range_validator(self, 10, 30)])

You could use functools.partial :您可以使用functools.partial

def range_validator(instance, attribute, value, min_value, max_value):
    lv = len(value)
    if min_value > lv or lv > max_value:
        raise ValueError("Must be between {} and {}".format(min_value, max_value))

@attrs
class C:
    x = attrib(validator=partial(range_validator, min_value=10, max_value=30))

Alternatively you can use a closure:或者,您可以使用闭包:

def make_range_validator(min_value, max_value):
    def range_validator(instance, attribute, value):
        lv = len(value)
        if min_value > lv or lv > max_value:
            raise ValueError("Must be between {} and {}".format(min_value, max_value))

    return range_validator

@attrs
class C:
    x = attrib(validator=make_range_validator(10, 30))

I personally like the closure factory approach better because they are more explicit about what you're doing.我个人更喜欢闭包工厂方法,因为它们更明确地说明你在做什么。 Partials always feel a bit ad-hoc to me, but that might just be me. Partials 对我来说总是感觉有点特别,但那可能只是我。

(Please note that I took the liberty to fix a logic bug in your validator – you may want to apply it too. :)) (请注意,我冒昧地修复了您验证器中的逻辑错误——您可能也想应用它。:))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM