传递无值后,如何将默认值应用于python数据类字段?

时间:2019-06-19 10:14:49

标签: python-3.x default-value

编辑:为清楚起见,我需要一个class来接受许多参数,我知道将提供所有参数,但有些参数可能以None的形式传递,在这种情况下,我的{ {1}}必须提供默认值。

我想用一些默认值来设置一个简单的class

dataclass

我希望能够获得第二个字段的默认值,但仍要为第三个字段设置一个值。我无法使用None来完成此操作,因为它很乐意被接受为我的字符串的值:

@dataclass
class Specs1:
    a: str
    b: str = 'Bravo'
    c: str = 'Charlie'

我想出了以下解决方案:

r1 = Specs1('Apple', None, 'Cherry') # Specs1(a='Apple', b=None, c='Cherry')

似乎表现出预期的行为:

@dataclass
class Specs2:
    def_b: ClassVar = 'Bravo'
    def_c: ClassVar = 'Charlie'
    a: str
    b: str = def_b
    c: str = def_c

    def __post_init__(self):
        self.b = self.def_b if self.b is None else self.b
        self.c = self.def_c if self.c is None else self.c

但是,我觉得这很丑陋,也许我在这里错过了一些东西。我的实际班级会有更多字段,因此只会变得更难看。

编辑:我应该补充一点,传递给该类的参数不包含任何内容,并且我对此方面没有控制权。

6 个答案:

答案 0 :(得分:2)

这是另一种解决方案。

定义DefaultValNoneRefersDefault类型:

from dataclasses import dataclass, fields

@dataclass
class DefaultVal:
    val: Any


@dataclass
class NoneRefersDefault:
    def __post_init__(self):
        for field in fields(self):

            # if a field of this data class defines a default value of type
            # `DefaultVal`, then use its value in case the field after 
            # initialization has either not changed or is None.
            if isinstance(field.default, DefaultVal):
                field_val = getattr(self, field.name)
                if isinstance(field_val, DefaultVal) or field_val is None:
                    setattr(self, field.name, field.default.val)

用法:

@dataclass
class Specs3(NoneRefersDefault):
    a: str
    b: str = DefaultVal('Bravo')
    c: str = DefaultVal('Charlie')

r3 = Specs3('Apple', None, 'Cherry')  # Specs3(a='Apple', b='Bravo', c='Cherry')

编辑:重写NoneRefersDefault使得以下操作也可以实现:

@dataclass
r3 = Specs3('Apple', None)  # Specs3(a='Apple', b='Bravo', c='Charlie')

答案 1 :(得分:1)

我了解您只需要位置参数。这可以通过在线条件(出于代码可读性)来实现。

class Specs():
    def __init__(self, a=None,b=None,c=None):
        self.a = a if a is not None else 'Apple'
        sefl.b = b if b is not None else 'Bravo'
        self.c = c if c is not None else 'Cherry'
example = Specs('Apple', None, 'Cherry')

如果您愿意的话,可以不用 init 方法来完成此方法。

但是,您可以考虑使用具有命名参数的 __ init __()方法。

class Specs():
    def __init__(self, a = 'Apple', b = 'Bravo', c = 'Cherry'):
        self.a = a
        self.b = b
        self.c = c
example = Specs('Apple', c = 'Cherry')

答案 2 :(得分:1)

简单的解决方案是仅在 __post_init__() 中实现默认参数!

@dataclass
class Specs2:
    a: str
    b: str
    c: str

    def __post_init__(self):
        if self.b is None:
            self.b = 'Bravo'
        if self.c is None:
            self.c = 'Charlie'

(代码没有经过测试。如果我有一些细节错误,那不是第一次)

答案 3 :(得分:0)

使用基于键的参数。您可以只做r2 = Specs1('Apple', c='Cherry')。您不必使用无。请参阅here

输出:

Specs1(a='Apple', b='Bravo', c='Cherry')

答案 4 :(得分:0)

不太清楚您要对班级做什么。这些默认值应该不是属性吗?

也许您需要类使用的定义具有默认参数,例如:

def printMessage(name, msg = "My name is "):  
    print("Hello! ",msg + name)

printMessage("Jack")

同样的情况适用于类。

关于“无”的类似辩论可以在这里找到:Call function without optional arguments if they are None

答案 5 :(得分:0)

在数据类中,您可以访问类属性的默认值:Specs.b 如果需要,您可以检查 None 并传递默认值

代码:

dataclasses.dataclass()
class Specs1:
    a: str
    b: str = 'Bravo'
    c: str = 'Charlie'
a = 'Apple'
b = None
c = 'Potato'
specs = Specs1(a=a, b=b or Specs1.b, c=c or Specs1.c)
>>> specs
Specs1(a='Apple', b='Bravo', c='Potato')