簡體   English   中英

具有可選屬性的 python 數據類

[英]python dataclasses with optional attributes

from dataclasses import dataclass

@dataclass
class CampingEquipment:
    knife: bool
    fork: bool
    missing_flask_size: ? # removed field() per answers below.
    
kennys_stuff = {
    'knife':True,
    'fork': True
}

print(CampingEquipment(**kennys_stuff))

給我:

TypeError: CampingEquipment.__init__() missing 1 required positional argument: 'missing_flask_size'

你如何制作數據類的可選屬性?

編輯

我所說的可選的意思並不清楚。 可選我的意思是__dict__可能包含鍵“missing_flask_size”或不包含。 如果我設置了一個默認值,那么密鑰就會在那里,並且在某些情況下不應該在那里。 我想檢查它的類型是否存在。 我嘗試將字段(init = False)移動到類型位置(在冒號之后),這樣我就可以更明確地說明我想要的可選內容是鍵而不是值。 這讓包括我在內的每個人都感到困惑,所以它被刪除了。

所以我希望這個測試通過:

with pytest.raises(AttributeError):
    ce = CampingEquipment(**kennys_stuff)
    print(ce.missing_flask_size)

field object 應該與=一起使用,就像默認值一樣,而不是:像注釋一樣。

為字段指定init=False意味着調用者根本無法為其傳遞值。 init=False字段應該在__post_init__中設置,如下所示

@dataclass
class Example:
    a: int
    b: int
    c: int = field(init=False)

    def __post_init__(self):
        self.c = self.a + self.b

print(Example(1, 2).c) # prints 3

如果您想讓調用者可選地提供一個值,您可以設置一個默認值。 如果調用者未提供值,則將使用默認值:

@dataclass
class Example:
    a: int
    b: int
    c: int = -1

print(Example(1, 2).c) # prints -1
print(Example(1, 2, 3).c) # prints 3

不可能使用數據類來創建有時存在但有時不存在的屬性,因為生成的__init____eq____repr__等硬編碼了它們檢查的屬性。

但是,可以使用可選參數創建一個數據類,該參數使用屬性的默認值(當未提供時)。

from dataclasses import dataclass
from typing import Optional

@dataclass
class CampingEquipment:
    knife: bool
    fork: bool
    missing_flask_size: Optional[int] = None
    
kennys_stuff = {
    'knife':True,
    'fork': True
}

print(CampingEquipment(**kennys_stuff))

並且可以使用__init__接受但不是實際字段的參數創建數據類。 所以你可以做這樣的事情:

from dataclasses import dataclass, InitVar
from typing import Optional

@dataclass
class CampingEquipment:
    knife: bool
    fork: bool
    missing_flask_size: InitVar[Optional[int]] = None

    def __post_init__(self, missing_flask_size):
        if missing_flask_size is not None:
            self.missing_flask_size = missing_flask_size

如果您確實希望類具有該屬性或根本不具有該屬性,則可以對您的數據類進行子類化並創建一個工廠 function ,該工廠根據是否存在該missing_flask_size屬性創建一個 class 或另一個:

from dataclasses import dataclass

@dataclass
class CampingEquipment:
    knife: bool
    fork: bool


@dataclass
class CampingEquipmentWithFlask:
    missing_flask_size: int


def equipment(**fields):
    if 'missing_flask_size' in fields:
        return CampingEquipmentWithFlask(**fields)
    else:
        return CampingEquipment(**fields)
    

kennys_stuff = {
    'knife':True,
    'fork': True
}

print(CampingEquipment(**kennys_stuff))

如果你真的想要(雖然我不推薦它),你甚至可以自定義__new__CampingEquipment以在給出missing_flask_size參數時返回該特殊子類的實例(盡管你需要設置init=False和在該課程上制作自己的__init__ )。

我也在尋找相同的方法並找到解決方法。 如果有條件,只需彈出您不想要的項目。 像這樣

@dataclass
class Element:
    type: str
    src: str
    scale: Scale 
    duration: float = -1
    start: float = 0
    extra_time: float = 0
    cache: bool = True

    def get_data(self) -> None:
        if self.type != "image":
            self.__dict__.pop('scale')
            return self.__dict__
        if self.type == "image":
            return self.__dict__

只需使用條件彈出您不想要的項目並調用此方法 get_data()。 希望這會有所幫助。

只需向可選字段添加一個值

@dataclass
class CampingEquipment:
   knife: bool
   fork: bool
   missing_flask_size = None

# CampingEquipment(knife=True, fork=True, missing_flask_size=None)

也請參閱這篇文章如何在繼承的數據類中創建可選字段?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM