2 回答

TA貢獻1856條經驗 獲得超17個贊
Python 及其社區正在努力解決“結構”問題:如何最好地將相關值分組到復合數據對象中,以允許邏輯/輕松訪問組件(通常按名稱)。有許多相互競爭的方法:
collections.namedtuple
實例字典(帶有一組固定/已知的鍵)
屬性可訪問的字典(如stuf)
該ATTRS庫
PEP 557數據類
為每種結構類型手工制作的普通舊定制對象
每個位置/插槽的類似
tuple
和list
隱含含義的序列(過時但非常常見)等。
“應該有一種——最好只有一種——明顯的方法來做到這一點?!?/p>
無論是typing
圖書館和Mypy,像在大的Python社區,同時與如何更有效地定義類型/模式,包括復合對象掙扎。您鏈接到的討論是努力尋找前進道路的一部分。
NamedTuple
是collections.namedtuple
工廠產生的結構化對象的類型超類;TypedDict
a Mypy 嘗試定義使用固定模式字典時出現的鍵和相應類型的值。如果您只是考慮“我有一組固定的鍵應該映射到一組固定的鍵入值”,那么它們是相似的。但是由此產生的實現和約束是非常不同的。袋子和盒子一樣嗎?也許。也許不是。取決于您的觀點以及您想如何使用它們。倒酒,開始討論!
NamedTuple
順便說一下,現在是 Python 的正式組成部分。
from typing import NamedTuple
class Employee(NamedTuple):
name: str
id: int
TypedDict開始作為一個實驗性的 Mypy 功能開始生活,將打字與字典的異構、面向結構的使用進行斗爭。然而,從 Python 3.8 開始,它被納入標準庫。
try:
from typing import TypedDict # >=3.8
except ImportError:
from mypy_extensions import TypedDict # <=3.7
Movie = TypedDict('Movie', {'name': str, 'year': int})
還可以使用基于類的類型構造函數:
class Movie(TypedDict):
name: str
year: int
盡管存在分歧,兩者NamedTuple并TypedDict鎖定特定的鍵被使用,并且該類型的對應于每個鍵的值。因此,它們的目標基本相同:成為復合/結構類型的有用類型機制。
Python 的標準typing.Dict側重于更同質的并行映射,定義鍵/值類型,而不是鍵本身。因此,它在定義碰巧存儲在字典中的復合對象時不是很有用。
ConnectionOptions = Dict[str, str]

TA貢獻1846條經驗 獲得超7個贊
NamedTuple
如果可能的話,如果我想凍結這些值,我會去。否則我會使用數據類。
from dataclasses import dataclass
from typing import NamedTuple, TypedDict
from enum import Enum
class Gender(Enum):
? ? MALE = "male"
? ? FEMALE = "female"
## Class definition: Almost the same
@dataclass
class UserDataC:
? ? name: str
? ? gender: Gender
class UserTuple(NamedTuple):
? ? name: str
? ? gender: Gender
class UserNDict(TypedDict):
? ? name: str
? ? gender: Gender
## Object Creation: Looks the same
anna_datac = UserDataC(name="Anna", gender=Gender.FEMALE)
anna_tuple = UserTuple(name="Anna", gender=Gender.FEMALE)
anna_ndict = UserNDict(name="Anna", gender=Gender.FEMALE)
## Mutable values vs frozen values
anna_datac.gender = Gender.MALE
# anna_tuple.gender = Gender.MALE? # AttributeError: can't set attribute
anna_ndict["gender"] = Gender.MALE
# AttributeError: 'dict' object has no attribute 'gender'
# anna_ndict.gender = Gender.MALE
## New attribute
# Note that you can add new attributes like this.
# Python will not complain. But mypy will.
anna_datac.password = "secret"? # Dataclasses are extensible
# anna_tuple.password = "secret"? # AttributeError - named tuples not
# anna_ndict.password = "secret"? # AttributeError - TypedDict not
anna_ndict["password"] = "secret"
## isinstance
assert isinstance(anna_tuple, tuple)
assert isinstance(anna_ndict, dict)
為什么我更喜歡 NamedTuple 而不是 namedtuple
我認為寫和讀更直觀。另外,您可以為 mypy 提供更多檢查的可能性:
class UserTuple(NamedTuple):
? ? name: str
? ? gender: Gender
# vs
UserTuple = namedtuple("UserTuple", ["name", "gender"])
為什么我更喜歡元組而不是字典
如果我不需要事物可變,我喜歡它們不是可變的。這樣我可以防止意外的副作用
添加回答
舉報