[英]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.