简体   繁体   English

创建在读取时引发异常的值类型

[英]Creating value type that raises exception on reading

How do I create a value type that raises an exception when read?如何创建读取时引发异常的值类型?

For example:例如:

from dataclasses import dataclass, field

Missing = ...


@dataclass
class A:
    a: int = field(default=None)  # <- value can be None
    b: int = field(default=Missing)  # <- can be Missing until you try to access it

    def print(self):
        for i in [self.a, self.b]:
            print(i)  # <- raises ValueError if i is Missing

In Python, it seems there is always a way for anything :-)在 Python 中,似乎总有办法解决任何问题 :-)

It appears you can solve this by a clever use of a descriptor value as a dataclass field, as illustrated below.您可以通过巧妙地将描述符值用作数据类字段来解决此问题,如下图所示。 I would also read more on the section on Validators to understand a little bit more about how descriptors work.我还将阅读有关验证器部分的更多信息,以了解更多关于描述符如何工作的信息。

from dataclasses import dataclass


# create `_MissingType` class
_MissingType = type('_MissingType', (), {'__bool__': lambda self: False})

# create a singleton for that class
Missing = _MissingType()


class MissingValidator:
    __slots__ = ('default', 'private_name')

    # You may or may not want a default value
    def __init__(self, default=Missing):
        self.default = default

    def __set_name__(self, owner, name):
        self.private_name = '_' + name

    # override __get__() to return a default value if one is not passed in to __init__()
    def __get__(self, obj, obj_type=None):
        try:
            value = getattr(obj, self.private_name)

            if value is Missing:
                cls_name = obj_type.__qualname__
                public_name = self.private_name.lstrip('_')
                raise ValueError(f'Missing value for field `{public_name}` in class `{cls_name}`')

            return value

        except AttributeError:
            return self.default

    def __set__(self, obj, value):
        setattr(obj, self.private_name, value)


@dataclass
class A:
    a: int = None  # <- value can be None
    b: int = MissingValidator()  # <- can be Missing until you try to access it

    def print(self):
        for i in [self.a, self.b]:
            print(i)  # <- raises ValueError if i is Missing


A(b=3).print()
# None
# 3

A(a=42).print()
# raises:
#   ValueError: Missing value for field `b` in class `A`

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

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