【问题标题】:Initialize a TypedDict and fill keys & values later初始化 TypedDict 并稍后填充键和值
【发布时间】:2021-01-20 07:17:26
【问题描述】:

我有一个字典,其中键和值的类型是固定的。我想在TypedDict 中定义类型如下:

class MyTable(TypedDict):
    caption: List[str]
    header: List[str]
    table: pd.DataFrame
    epilogue: List[str]

我有一个返回MyTable 的函数。我想先定义一个空的(Typed)dict 并填写键和值。

def returnsMyTable():
    result = {}
    result['caption'] = ['caption line 1','caption line 2']
    result['header'] = ['header line 1','header line 2']
    result['table'] = pd.DataFrame()
    result['epilogue'] = ['epilogue line 1','epilogue line 2']
    return result

这里 MyPy 抱怨需要对结果进行类型注释。我试过这个:

result: MyTable = {}

但随后 MyPy 抱怨缺少密钥。同样,如果我定义了键但将值设置为None,它会抱怨值的类型不正确。

是否可以先将 TypedDict 初始化为空 Dict,然后再填写键和值? docs 似乎表明它是。

我想我可以先将值定义为变量,然后再组装MyTable,但我正在处理要添加类型提示的遗留代码。所以我想尽量减少工作。

【问题讨论】:

  • returnsMyTable 不只包含一个 dict 文字,立即分配键和值有什么原因吗?
  • 由于值的推导相当复杂,因此在 1 行中创建 MyTable 是不可行的。就像我写的那样,我可以首先将这些值定义为单独的值,但我正在处理以这种方式设置的遗留代码。这适用于result = MyTable(header=[''],caption=[''],table=pd.DataFrame(),epilogue=['']),但似乎相当不合Python
  • 除非您澄清“遗留代码”的问题,否则我认为我们无法真正帮助您。如果您知道结果是正确的,唯一的通用解决方案是# type: ignore 问题。
  • 对于“遗留代码”,我只是指一个预先存在的代码库,我正在向其中添加类型提示。它没有问题,但除了添加类型提示之外,我想进行最小的更改。

标签: python mypy typeddict


【解决方案1】:

你可能想要在这里设置整体,但我会三思而后行。

引用the PEP

默认情况下,所有键都必须存在于 TypedDict 中。可以通过指定整体来覆盖它。下面是如何使用基于类的语法来做到这一点:

class MyTable(TypedDict, total=False):
    caption: List[str]
    header: List[str]
    table: pd.DataFrame
    epilogue: List[str]

result: MyTable = {}
result2: MyTable = {"caption": ["One", "Two", "Three"]}

正如我所说,请三思而后行。总计TypedDict 为您提供了一个非常好的保证,即所有项目都将存在。也就是说,因为 MyPy 不允许没有“标题”的结果存在,所以您可以安全地调用 cap = result["caption"]

如果您设置 total=False,则该保证将消失。假设您使用 MyTable 的频率比实际使用频率高得多,那么在使用它时获得额外的安全保证可能是一笔不错的交易。

就个人而言,我会保留total=False 用于创建代码有时确实会遗漏某些内容并且任何使用它的代码都必须处理的情况。如果只是需要几行来初始化,我会这样做:

def returnsMyTable():
    result = {}
    result_caption = ['caption line 1','caption line 2']
    result_header = ['header line 1','header line 2']
    result_table = pd.DataFrame()
    result_epilogue = ['epilogue line 1','epilogue line 2']
    result = {
        "caption": result_caption, 
        "header": result_header, 
        "table": result_table, 
        "epilogue": result_epilogue
    }
    return result

【讨论】:

  • 谢谢。我同意删除总体要求是不可取的(违背了类型提示的目的)。您的最后一个建议是我的意思是“将值定义为变量并稍后组装MyTable”。正如我所说,docs 表明常规的dicts (d: Dict[str, int] = {}) 是可能的。但显然不适用于TypedDicts。
  • 没错。常规的 dict 表示法所说的是keys() 中的所有内容都是字符串,values() 中的所有内容都是 int。 MyPy 不会检查您的d 是否会在您将一些内容放入其中几行后满足这一点。它正在检查它是否已经完成。键或值中没有任何不是字符串或 int 的内容(因为键或值中没有任何内容!),因此它是合法的。
猜你喜欢
  • 2021-11-02
  • 2021-10-13
  • 1970-01-01
  • 2014-10-04
  • 1970-01-01
  • 1970-01-01
  • 2015-08-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多