gpt4 book ai didi

Python键入: typed dictionary or defaultdict extending classes

转载 作者:行者123 更新时间:2023-12-03 20:17:10 24 4
gpt4 key购买 nike

我有一段旧的python代码,可解析严格格式化的文本文件(存储字符串以进行本地化)。因为该结构是分层结构,并且某些元素可能存在或可能不存在,所以该程序使用嵌套的defaultdict来表示它。就像是:

terms = defaultdict(lambda: defaultdict(str)) # dict<key, dict<lang, translation>>

因为这些字典没有类型(因为它们的成员可以是任何类型),并且它们是嵌套的,并且因为我需要在该层次结构中添加另一个级别,所以我决定在该程序中添加类型:
from typing import Tuple, Dict, Set, List, NewType

Key = NewType('Key', str)
Lang = NewType('Lang', str)
Translation = NewType('Translation', str)
PLIndex = NewType('PLIndex', int)

但是,我一辈子都无法弄清楚如何重写上面的 terms =行以使那些嵌套的 defaultdict键入。

我最终要做的只是将 dict包装到我的类型中,看起来不太好:
class Forms:
def __init__(self):
self.dct: Dict[PLIndex, Translation] = {}

def __getitem__(self, item: PLIndex) -> Translation:
return self.dct[item]

def __setitem__(self, key: PLIndex, value: Translation) -> None:
self.dct[key] = value


class Translations:
def __init__(self):
self.dct: Dict[Lang, Forms] = {}

def __getitem__(self, item: Lang) -> Forms:
if item not in self.dct:
self.dct[item] = Forms()
return self.dct[item]

def __setitem__(self, key: Lang, value: Forms) -> None:
self.dct[key] = value

def items(self):
return self.dct.items()


class Terms:
def __init__(self):
self.dct: Dict[Key, Translations] = {}

def __getitem__(self, item: Key) -> Translations:
if item not in self.dct:
self.dct[item] = Translations()
return self.dct[item]

def __setitem__(self, key: Key, value: Translations) -> None:
self.dct[key] = value

def __len__(self):
return len(self.dct)

def items(self):
return self.dct.items()

...

terms = Terms()

有没有一种方法可以将 FormsTranslations和其他类型声明为 NewType/ dictdefaultdict,并能够以对嵌套字典强制使用正确类型的方式重写 terms =?还是可以扩展 dict/ defaultdict(而不是包装它们)并能够强制使用正确的类型?还是完全有更好的方法?

最佳答案

在我看来,包装字典似乎毫无意义(因为它没有添加任何新功能,但您仍然必须对其进行维护),因此,如果可能的话,我将避免使用它。

现在,以下内容对我有用:

from collections import defaultdict
from typing import Tuple, Dict, DefaultDict, Set, List, NewType

Key = NewType('Key', str)
Lang = NewType('Lang', str)
Translation = NewType('Translation', str)
PLIndex = NewType('PLIndex', int)

FormsDict = DefaultDict[PLIndex, Translation]
TranslationsDict = DefaultDict[Lang, FormsDict]
TermsDict = DefaultDict[Key, TranslationsDict]

terms: TermsDict = defaultdict( # TermsDict
lambda: defaultdict( # TranslationsDict
lambda: defaultdict( # FormsDict
lambda: Translation("") # Default value "" (as Translation)
)
)
)

我已经用 mypy --strict测试了它,并通过了验证。将其与 defaultdict一起使用并仍通过验证,看来您将需要 cast
from typing import cast

terms[Key("key1")].update(
cast(TranslationsDict, {
Lang("en_GB.UTF-8"): cast(FormsDict, {
PLIndex(100): Translation("key1")
})
})
)

print(terms)

输出:
defaultdict(<function <lambda> at 0x107d31cb0>, {
'key1': defaultdict(<function <lambda>.<locals>.<lambda> at 0x107d31d40>, {
'en_GB.UTF-8': {100: 'key1'}})})

关于Python键入: typed dictionary or defaultdict extending classes,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59518521/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com