检查数据类字段是否具有默认值的Python方法

时间:2018-12-03 08:14:03

标签: python python-3.x python-dataclasses

我最近一直在使用python 3.7,并且正在寻找利用新数据类的方法。基本上,我有一个遍历数据类字段并检查它们是否具有默认值的方法:

from dataclasses import fields, MISSING

@classmethod
def from_json(cls)
    datacls_fields = fields(cls)
    for field in datacls_fields:
        if  (field.default != MISSING):
            #...

但是在官方文档中却说:

  

MISSING值是用于检测的哨兵对象   如果提供了default和default_factory参数。这个   由于没有值是默认的有效值,因此使用了哨兵。 无代码   应该直接使用MISSING值。

有人知道一种更好/更多的pythonic方法吗?

2 个答案:

答案 0 :(得分:1)

这是MISSING中python源代码中dataclasses.py的定义:

# A sentinel object to detect if a parameter is supplied or not.  Use
# a class to give it a better repr.
class _MISSING_TYPE:
    pass
MISSING = _MISSING_TYPE()

定义非常清楚,其用例只是检查是否已提供参数,并区分None的值和未提供的值:

def my_func(a=MISSING):
    if a is not MISSING:
        # a value has been supplied, whatever his value

因此完全可以在代码中使用它进行价值比较。通过告诉没有代码应直接使用MISSING值,他们只是警告我们该变量没有特定用途(用于比较的其他用途),并且不应在代码中使用,以避免意外行为。

您应该更新代码以使用更多的Python语法is not MISSING

from dataclasses import fields, MISSING

@classmethod
def from_json(cls)
    datacls_fields = fields(cls)
    for field in datacls_fields:
        if field.default is not MISSING:

答案 1 :(得分:1)

我认为pythonic解决方案依赖于使用魔术__dict__(文档:https://docs.python.org/3/library/stdtypes.html#object.__dict__)。

class Foo:
def __init__(self, a=1, b=2, c=3):
    self.a = a
    self.b = b
    self.c = c

x = Foo()
y = Foo(a=5)
print(x.__dict__ == Foo().__dict__)  # True
print(y.__dict__ == Foo().__dict__)  # False

基本上,当在对象实例上使用时,它将返回一个字段值对(键值)的字典。

为了检查它们是否为默认值,我只需将给定实例上的此字典与在默认无名对象上创建的相同字典进行比较。

该代码可能更具解释性。

P.S。这是所有字段是否都具有默认值的答案。如果您需要确切地知道哪些字段没有默认值的信息,这是我建议的解决方案(基于与上述相同的逻辑,但是我们不比较字典是否相等,而是发现它们之间的区别):

# Need the actual fields back?
x_dict = x.__dict__
y_dict = y.__dict__
default = Foo().__dict__
print(dict(set(x_dict.items()) - set(default.items())))
print(dict(set(y_dict.items()) - set(default.items())))

使用此代码时的输出:

{}
{'a': 5}

有关如何查找两个词典之间差异的详细信息,请参见How to get the difference between two dictionaries in Python?