在数据类中声明默认值时使用 self

Use self while declaring default value in dataclass

我想创建一个 python dataclass,其中一个变量基于另外两个变量。 例如

@dataclass
class phone_number:
    number: str
    country_code: str = "+1 "
    full_number: str = country_code + number

所以当我调用 phone_number.full_number 我得到例如 "+1 123456789".

但如果我需要的话,能够传递一个已经满的 phone 号码对我来说也很重要 phone = phone_number(number="", full_number="+1 123456789")

另外,当我在做的时候,是否可以使变量 numberfull_number 互斥,所以如果给定数字,我不需要传递 full_number 反过来呢?

我会使用 property:

@dataclass
class phone_number:
    number: str
    country_code: str = "+1 "

    @property
    def full_number(self):
        return self.country_code + self.number

但此时您还不如使用普通的 class,特别是由于其他 2 个要求:

from typing import Optional

class phone_number:
    def __init__(self, number: Optional[str] = None,
                 country_code: str = "+1",
                 full_number: Optional[str] = None):
        if number and full_number:
            raise ValueError('number and full_number are mutually exclusive')
        self.number = number
        self.country_code = country_code
        self._full_number = full_number or f'{country_code} {number}'

    @property
    def full_number(self):
        return self._full_number


print(phone_number(number='1234567').full_number)
# +1 1234567
print(phone_number(full_number='1234567').full_number)
# 1234567

是的,可以通过使用哨兵作为默认值(我只是在这里使用 None 来保持类型简单)。这样,您可以检查 __post_init__ 是否通过了自定义 full_number

from dataclasses import dataclass
from typing import Optional


@dataclass
class phone_number:
    number: str
    country_code: str = "+1 "
    full_number: Optional[str] = None

    def __post_init__(self):
        if self.full_number is None:
            self.full_number = self.country_code + self.number

下面是一些用法示例:

>>> phone_number("123"))
phone_number(number='123', country_code='+1 ', full_number='+1 123')

>>> phone_number("123", country_code="+44 "))
phone_number(number='123', country_code='+44 ', full_number='+44 123')

>>> phone_number("123", full_number="789"))
phone_number(number='123', country_code='+1 ', full_number='789')

>>> phone_number("123", country_code="+44 ", full_number="789"))
phone_number(number='123', country_code='+44 ', full_number='789')