【问题标题】:Difference between defining typing.Dict and dict?定义typing.Dict和dict之间的区别?
【发布时间】:2016-09-02 10:00:39
【问题描述】:

我正在练习在 Python 3.5 中使用类型提示。我的一位同事使用typing.Dict

import typing


def change_bandwidths(new_bandwidths: typing.Dict,
                      user_id: int,
                      user_name: str) -> bool:
    print(new_bandwidths, user_id, user_name)
    return False


def my_change_bandwidths(new_bandwidths: dict,
                         user_id: int,
                         user_name: str) ->bool:
    print(new_bandwidths, user_id, user_name)
    return True


def main():
    my_id, my_name = 23, "Tiras"
    simple_dict = {"Hello": "Moon"}
    change_bandwidths(simple_dict, my_id, my_name)
    new_dict = {"new": "energy source"}
    my_change_bandwidths(new_dict, my_id, my_name)

if __name__ == "__main__":
    main()

它们都工作得很好,似乎没有区别。

我已阅读typing module documentation

typing.Dictdict 之间,我应该在程序中使用哪一个?

【问题讨论】:

  • 请注意,Python 实际上并不强制 类型提示。它们只是提示,它们不会在运行时甚至编​​译时用于强制类型。 Python 可能是强类型(与弱类型相反),它也是动态类型(与严格类型相反)。见Is Python strongly typed?。像 mypy 这样的外部工具可以使用这些提示来帮助您编写更好的代码,但是,在一个称为静态分析的过程中。
  • @MartijnPieters 我曾经喜欢在我的代码中与 MyPy 一起使用类型提示,并假装我可以使用具有类型安全性的 Python。不幸的是,它让我 A)代码不适用于
  • @cat:Facebook 员工将类型提示引入 Python,因为我们在向 PHP 中添加相同的功能方面取得了巨大的成功(参见 hack)。任何人都笑过,从来没有用几个工程师建立过一个大项目。
  • @MartijnPieters 不,def a(b: int) -> bool: 在 Python 2.7 中是一个语法错误,我认为在旧版本的 Python 3 中也是一个语法错误。
  • @cat:您在这里谈论的是 函数注释,这是 Python 3.0 中添加的语法。因此,唯一出现语法错误的版本是 2.7,这就是 mypy 支持将该信息放入 cmets 的原因。

标签: python dictionary type-hinting python-typing


【解决方案1】:

使用普通的typing.Dictdict 没有真正的区别,没有。

然而,typing.Dict 是一个Generic type *,它允许您指定键和值的类型,使其更加灵活:

def change_bandwidths(new_bandwidths: typing.Dict[str, str],
                      user_id: int,
                      user_name: str) -> bool:

因此,很可能在您的项目生命周期的某个时刻,您希望更精确地定义字典参数,此时将 typing.Dict 扩展为 typing.Dict[key_type, value_type] 是比替换 @ 更“小的”变化987654335@.

您可以在此处使用MappingMutableMapping 类型使其更加通用;由于您的函数不需要更改映射,我会坚持使用Mappingdict 是一种映射,但您可以创建其他也满足映射接口的对象,并且您的函数可能仍然可以使用这些对象:

def change_bandwidths(new_bandwidths: typing.Mapping[str, str],
                      user_id: int,
                      user_name: str) -> bool:

现在您清楚地告诉此函数的其他用户,您的代码实际上不会更改传入的new_bandwidths 映射。

您的实际实现只是期望一个可打印的对象。这可能是一个测试实现,但就目前而言,如果您使用 new_bandwidths: typing.Any,您的代码将继续工作,因为 Python 中的任何对象都是可打印的。


*:注意:如果您使用的是 Python 3.7 或更高版本,则可以使用 dict 作为泛型类型,前提是您以 from __future__ import annotations 开头模块,从 Python 3.9 开始,@ 987654345@(以及其他标准容器)supports being used as generic type even without that directive

【讨论】:

  • 有用的附加示例是字典值可以是不同的类型,例如{"name": "bob", "age" : 51},会不会是类似typing.Mapping[Union[str, int] 的东西?像 {"person": {"name":"bob", "age": 51} 这样的嵌套字典会是像 typing.Mapping[str, typing.Mapping[Union[str, int]] 这样的东西吗?像这样使用Union 让我很困扰,因为它不是一个严格的模式,因为没有排序。也许没关系,或者有其他选择吗?
  • 别在意Union 问题我看到它仍然是一个公开讨论github.com/python/typing/issues/28
  • 这个好像很有趣,有用,相关python.org/dev/peps/pep-0589
  • @GregHilston:啊,是的。
  • @xjcl:请参阅 python.org/dev/peps/pep-0484/#covariance-and-contravariance 了解更多信息。
【解决方案2】:

typing.Dictdict 的通用版本:

class typing.Dict(dict, MutableMapping[KT, VT])

dict 的通用版本。该类型的用法如下:

def get_position_in_index(word_list: Dict[str, int], word: str) -> int:
     return word_list[word]

这里可以指定dict中键和值的类型:Dict[str, int]

【讨论】:

    【解决方案3】:

    python org中所说:

    class typing.Dict(dict, MutableMapping[KT, VT])

    dict 的通用版本。用于注释返回类型。到 注释参数最好使用抽象集合类型 比如映射。

    这种类型可以如下使用:

    def count_words(text: str) -> Dict[str, int]:
        ...
    

    dict 不太通用,您将能够更改传入的映射。 实际上,在python.Dict 中,您指定了更多详细信息。

    另一个提示:

    3.9 版后已弃用:builtins.dict 现在支持 []。见PEP 585 和通用别名类型。

    【讨论】:

      猜你喜欢
      • 2011-02-14
      • 2016-03-26
      • 2013-10-07
      • 2014-08-01
      • 1970-01-01
      • 2011-07-21
      • 2011-03-26
      • 2011-09-30
      相关资源
      最近更新 更多