【问题标题】:What are the differences between Set, FrozenSet, MutableSet and AbstractSet in python typing module?python类型模块中Set、FrozenSet、MutableSet和AbstractSet有什么区别?
【发布时间】:2016-03-10 03:59:07
【问题描述】:

我正在尝试用类型注释我的代码,但在涉及集合时我有点困惑。我在PEP 484中读到了一些观点:

注意: Dict 、 List 、 Set 和 FrozenSet 主要用于注释返回值。对于参数,更喜欢下面定义的抽象集合类型,例如映射、序列或抽象集。

Set,重命名为 AbstractSet 。之所以需要更改名称,是因为类型模块中的 Set 意味着带有泛型的 set()。

但这无济于事。

我的第一个问题是:Set、FrozenSet、MutableSet和AbstractSet有什么共同点和不同点?

我的第二个问题是:为什么要尝试

from collections import FrozenSet

我明白了

ImportError: cannot import name 'FrozenSet'

?

我使用的是 Python 3.4,并且我已经通过 pip 安装了 mypy-lang。

【问题讨论】:

    标签: python python-3.x type-hinting frozenset


    【解决方案1】:

    注意注释和输入。 484 中讨论的想法是全新的,并在typing 模块中实现。该模块仅在 Python3.5 中可用(最新的 typing 也可从 pip 获得,适用于 Py2 和 Py3)。

    https://docs.python.org/3/library/typing.html

    您引用的注释来自 484 中的一个部分,开头是:

    要向 Python 3.5 以及旧版本开放静态类型检查的使用,需要统一的命名空间。为此,在标准库中引入了一个名为 typing 的新模块。

    注释列出的东西是注释类型,而不是实际的对象类(内置或来自collections)。不要混淆两者。

    注意DictListSetFrozenSet都是大写的,其中函数(和类型名称)是dictlistsetfrozenset。换句话说,要制作字典,您使用dict(){},而不是Dict

    注解是 3.0 的新功能(2.n 根本没有)。在常规解释器中,他们所做的只是填充函数的 __annotations__ 字典。解释器中没有使用或需要注释的内容。

    http://mypy-lang.org/ 将自己描述为一个实验性的打字检查器。您需要查看它的文档以了解它与 484 等的兼容性。

    https://docs.python.org/3/library/collections.abc.html#module-collections.abc 有一些抽象定义,我相信typing 使用。我从来没有用过这些。它们主要面向开发新对象类别的人,而不是“普通”用户。

    这个问题的typing 标签可能不是一个好主意。它的追随者不多,而且过于笼统。它没有引用这个 Python 模块。

    搜索 [python] 484 以了解其他处理这种注释风格的 SO 问题。

    https://github.com/python/typing - typing 开发存储库。

    在这个存储库中,python2/typing.py 文件(python2 反向端口)中有一个FrozenSet 定义,但在src/typing.py 中没有。我不确定这有什么意义。

    【讨论】:

    • 您好,感谢您的回复。我现在有了更清晰的想法(我知道注释类型和对象之间的区别,但不知道 mypy 的类型与 python3.5 的类型模块)。但是,我查看了这两个文档,但找不到对 PEP 484 中提到的 FrozenSet 的引用。我错过了什么吗?
    • 看起来他们没有将FrozenSet 添加到typingtyping 中的许多类都映射到 collections.abc,其中有 MutableSetAbstractSet,但没有 FrozenSet。所以此时FrozenSet只是PEP中的一个想法,仅此而已。
    • typing 模块有一个 github 存储库。探索它以了解将来可能添加的内容。
    • 看来typingmypy 必须一起使用。使用既能实现的功能,又能忘记 PEP 中的附加功能。并期待事情会发生变化,因为两者都在开发中。
    • 感谢您的澄清。我删除了标签类型 - 我同意这不是一个好主意(python 类型会更好,但不存在)。
    【解决方案2】:

    晚了两年,但无论如何......

    您可以将AbstractSetMutableSet 视为Java 中的接口或Python 中的抽象基类。 Python 的内置 set()frozenset() 是一种实现,但有人可以创建另一个完全不使用内置的实现。

    另一方面,FrozenSetSet 表示具体内置类 frozensetset 的类型。

    例如,“接口”类型没有union 方法,而具体类型有。所以:

    def merge(a: Set[str], b: Iterable[str]) -> Set[str]:
        return a.union(b)
    

    将类型检查就好了,但如果你将a 的类型更改为AbstractSet,mypy 会说:

    typetest.py:7: error: "AbstractSet[str]" has no attribute "union"

    【讨论】:

    • 为什么the docs 说AbstractSet 更适合输入参数呢? “要注释参数,最好使用抽象集合类型,例如 AbstractSet。”
    • @ProQ 如果您需要unionintersection,它也不起作用。我不知道为什么AbstractSet 不支持这些。
    【解决方案3】:

    这些类型名称确实有点混乱。在mypy Gitter上有过相关讨论,Guido提供了clarification

    typing.AbstractSettyping.MutableSet 是 ABC(抽象基类)的类型,而不是集合类型的具体实现:

    • typing.AbstractSetcollections.abc.Set 的类型,它是不可变集的 ABC(抽象基类)。
    • typing.MutableSetcollections.abc.MutableSet 的类型,它是可变集的 ABC。

    typing.Settyping.FrozenSet 是具体集合实现的类型,可在标准库中找到:

    • typing.Set 是 stdlib set 的类型,它是可变集的具​​体实现。
    • typing.FrozenSet 是 stdlib frozenset 的类型,它是不可变集合的具体实现。

    【讨论】:

      【解决方案4】:

      set 类型是可变的——可以使用 add() 和 remove() 等方法更改内容。由于它是可变的,它没有哈希值,不能用作字典键或另一个集合的元素。 freezeset 类型是不可变的和可散列的——它的内容在创建后不能更改;但是,它可以用作字典键或另一个集合的元素。

      来自:https://docs.python.org/3/library/stdtypes.html#frozenset

      您不需要包含它,它是内置的,您只需:

      cities = frozenset(["Frankfurt", "Basel","Freiburg"])

      在 3.4.2 中测试

      【讨论】:

      • 谢谢,我知道这些区别。问题是关于这些类型如何在类型模块中映射。如果我不清楚,我很抱歉。
      猜你喜欢
      • 2013-01-11
      • 1970-01-01
      • 2011-12-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-17
      • 2011-03-01
      • 2011-07-05
      相关资源
      最近更新 更多