首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python数据集验证:一种简单的方法?

Python数据集验证:一种简单的方法?
EN

Stack Overflow用户
提问于 2022-04-15 21:08:26
回答 1查看 1.5K关注 0票数 0

我试图了解python数据集验证是如何直接实现的。我正在使用棉花糖validate尝试这样做,但不了解验证是如何在数据块中实际运行的,或者它是否只是作为元数据字段(您必须相当笨拙地运行)。

我可以做一个__post_init__ (如建议的herehere)来直接对每个字段执行验证,但我觉得应该有一种简单、不可知的方法来根据所有字段的validate元数据(无论是在__init__还是其他地方)验证所有字段。

下面是一个示例脚本:

代码语言:javascript
复制
from dataclasses import dataclass, field
from marshmallow import validate


def null_validate(value):
    """Validation fn for dataclass"""
    if value is None:
        pass
    else:
        raise ValidationError("{value} should be a string for this dataclass field!")


@dataclass
class Testing:
    plus_minus_one: int = field(
        default=None,
        metadata=dict(
            required=False,
            validate=validate.OneOf([1, -1])
        )
    )
    max_one: int = field(
        default=None,
        metadata=dict(
            required=False,
            validate=validate.Range(max=1)
        )
    )
    null_field: str = field(
        default=None,
        metadata=dict(
            required=False,
            validate=null_validate
        )
    )

print("this passes")
it = Testing(1, 1, None)
print("this should fail")
it = Testing(10, 10, 10)

我按照如下方式运行它,但没有得到任何ValidationError,因此我知道验证不会在dataclass中神奇地发生:

代码语言:javascript
复制
% python testing.py
this passes
this should fail

因此,我可以做的是将这样的__post_init__方法添加到dataclass中:

代码语言:javascript
复制
def __post_init__(self):
    for data_field in self.__dataclass_fields__:
        self.__dataclass_fields__[data_field].metadata["validate"](
            self.__dict__[data_field]
        )

在这种情况下,验证或多或少是在论证的基础上进行的:

代码语言:javascript
复制
% python testing.py
this passes
this should fail
Traceback (most recent call last):
  File "testing.py", line 47, in <module>
    it = Testing(10, 10, 10)
  File "<string>", line 6, in __init__
  File "testing.py", line 41, in __post_init__
    self.__dataclass_fields__[data_field].metadata["validate"](self.__dict__[data_field])
  File "/Users/max.press/miniconda3/envs/test_env/lib/python3.7/site-packages/marshmallow/validate.py", line 569, in __call__
    raise ValidationError(self._format_error(value))
marshmallow.exceptions.ValidationError: Must be one of: 1, -1.

但这似乎相当笨重,而且似乎很难实现比这更复杂的验证。似乎我应该能够在传入参数时验证“预先”,而无需更改任何内容。

是移动到完整marshmallow-dataclass的解决方案吗?可能作为一个Schema来处理这个问题。

EN

回答 1

Stack Overflow用户

发布于 2022-04-15 21:08:26

事实证明,通过使用棉花糖数据类型和它们的Schema()方法,您可以很容易地做到这一点。

下面的代码显示了在不使用__post_init__的情况下所需的行为,不过我显然需要阅读更多关于棉花糖的内容:

代码语言:javascript
复制
from dataclasses import dataclass, field
from marshmallow import validate, Schema
from marshmallow_dataclass import dataclass



def null_validate(value):
    """Validation fn for dataclass"""
    if value is None:
        pass
    else:
        raise ValidationError("{value} should be a string for this dataclass field!")


@dataclass
class Testing:
    plus_minus_one: int = field(
        default=None,
        metadata=dict(
            required=False,
            validate=validate.OneOf([1, -1])
        )
    )
    max_one: int = field(
        default=None,
        metadata=dict(
            required=False,
            validate=validate.Range(max=1)
        )
    )
    null_field: NoneType = field(
        default=None,
        metadata=dict(
            required=False,
            validate=null_validate
        )
    )

print("this passes")
it = Testing.Schema().load({"plus_minus_one": 1, "max_one": 1, "null_field": None})
print("this should fail")
it = Testing.Schema().load({"plus_minus_one": 10, "max_one": 10, "null_field": 10})

当它运行时,我得到了想要的结果:

代码语言:javascript
复制
this passes
this should fail
[...]
marshmallow.exceptions.ValidationError: {'null_field': ['Not a valid string.'], 'plus_minus_one': ['Must be one of: 1, -1.'], 'max_one': ['Must be less than or equal to 1.']}
票数 -2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71888968

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档