Python 3.10 不这么认为:
Python 3.10.6 | packaged by conda-forge | (main, Aug 22 2022, 20:38:29) [Clang 13.0.1 ] \
on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from typing import Iterable
>>> isinstance(list[str], Iterable)
False
>>> list(list[str])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'types.GenericAlias' object is not iterable
Python 3.11 认为它是:
Python 3.11.0 | packaged by conda-forge | (main, Jan 15 2023, 05:44:48) [Clang 14.0.6 ] \
on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from typing import Iterable
>>> isinstance(list[str], Iterable)
True
>>> list(list[str])
[*list[str]]
如果它是一个可迭代对象,那么迭代它的结果应该是什么?
*list[str]
项似乎是其自身或类型变量元组的
unpacking
这里发生了什么?我知道 python 中的输入处于不断变化和快速发展的状态,但我真的不知道如何解释这一点。
你对 Python 3.10 和 3.11 中行为差异的观察是正确的,解释与 Python 中类型提示的演变有关,特别是与
typing.GenericAlias
的引入有关。
Python 3.10 及更早版本
在 3.10 中,
list[str]
等类型提示
未被视为可迭代的
。
isinstance(list[str], Iterable)
返回
False
,因为在运行时,它主要被视为
typing._GenericAlias
(在旧版本中为
typing.GenericAlias
)。它们没有实现
__iter__
方法,因此不能被迭代。
Python 3.11
从 3.11 开始,对
typing.GenericAlias
(
list[str]
等类型提示的底层类型)进行了更改,使其
可迭代
。此更改旨在允许在类型提示上下文中进行更强大的操作。
当你迭代
list[str]
时,你实际上是在迭代类型参数,在本例中只有一个:
str
。因此,
list(list[str])
返回
[*list[str]]
,这基本上是类型参数的列表(使用
*
语法)。
发生了什么?
这种变化是 Python 类型提示逐渐成熟的一部分。使
typing.GenericAlias
可迭代,打开了一些可能性,尤其是在使用更复杂的类型提示和泛型时。
这是否意味着
list[str]
现在是一个可迭代的对象,就像一个字符串列表?
不完全是。虽然现在可以迭代
typing.GenericAlias
实例,但这并不意味着它们在运行时被视为常规的可迭代对象。迭代它们的结果是类型参数,而不是值的集合。
关键要点
-
list[str]
本身并不是一个字符串列表;它是一种类型提示,用于描述包含字符串的列表。 -
从 Python 3.11 开始,
typing.GenericAlias
实例(如list[str]
)是可迭代的,但它们迭代的是类型参数。 - 此更改主要影响使用类型提示和泛型的代码,并且可能不会影响大多数日常 Python 代码。
我希望这能澄清一下!
标签:python,python-typing From: 75695843