为什么List不能包含多种类型?

30

您可以在元组或列表中混合使用类型。为什么不能在类型提示中指定?

>>> from typing import Tuple, List
>>> t = ('a', 1)
>>> l = ['a', 1]

>>> t2: Tuple[str, int] = ('a', 1)
>>> l2: List[str, int] = ['a', 1]

TypeError: Too many parameters for typing.List; actual 2, expected 1

因为通常不会在列表和其他序列中混合使用这样的类型。如果您想要一个既可以是字符串又可以是整数的东西列表,您可以这样做,但不能按位置。Tuple是一个特殊情况。 - jonrsharpe
4个回答

51
在类型理论中,列表是包含同一类型值的结构。因此,List 只接受一个类型,并且该列表中的每个元素都必须具有该类型。但是,类型理论还提供了和类型,可以将其视为围绕从某个固定类型集合中选择的一个值的包装器。和类型由 typing.Union 支持。要指定列表是 intstr 值的混合,请使用:
List[Union[str, int]]

作为类型提示。

相比之下,元组是“乘积类型”的一个例子,即由一组固定类型组成的类型,并且其值是从乘积类型中每个类型中选择的值的集合。 Tuple[int,int,int]Tuple[str,int]Tuple[int,str] 都是不同的类型,它们通过产品中类型的数量和它们出现的顺序来区分。


11

虽然你可以使用 Union,但是一般来说,如果能够避免,列表应该是同质的而不是异质的:

from typing import List, Union
lst: List[Union[str, int]] = [1, 'a']

myp 至少可以很好地接受这个。

这意味着你的列表访问器将返回一个联合类型,通常需要在任何下游函数中处理不同可能的类型。接受联合类型通常不会有太大问题。


1
我恰好发布了我的一个问题,说明了我在 Union 中遇到的问题... - juanpa.arrivillaga

4

针对现在的读者:如果你正在使用 Python 3.10 及以上版本,类型支持已经有了很大的变化。Union 可以用 | 缩写,并且对于大多数常见类,你不再需要导入 typing。因此:

from typing import List, Union
my_list : List[Union[str, float]] = ["example", 0, 1, 2]

等同于:

my_list : list[str | float] = ["example", 0, 1, 2]

您可以在PEP 604, PEP 612, PEP 613PEP 647中找到每个细节。

然而,如果您想指定列表中每个元素的类型,例如从函数返回值时,应该使用类型tuple而不是list。在这种情况下,您应该使用逗号而不是|

def my_list(text : str, number : float) -> tuple[str, float] :
    return text, number

默认情况下(无论类型),此函数返回一个元组。如果您绝对需要一个列表,请执行以下操作:

def my_list(text : str, number : float) -> tuple[str, float] :
    return [text, number]

1

使用ListUnion的方法在某些情况下是可行的,但容易导致错误并不是最佳实践。这就是为什么List不允许多种类型的原因。让我解释一下。

错误的方式

做这件事的错误方式(就像其他答案所写的那样)是这样的。

from typing import Union, List
List[Union[str, int]]

有两个问题。

  1. 您不能多次重复类型
  2. 当列表被更新或更改时,类型提示可能变得不准确。

虽然它可能在短期内解决问题,但这不是在Python中使用类型提示的正确方式。

正确的方法1:同类列表

这是您使用列表的地方。列表是可变的,因此如果您添加了类型,并更改了列表,则类型不再准确。因此,您永远不应该为不同类型使用List

from typing import List
my_list = List[str]

正确的方法2:非同质元组

如果您确实需要对列表进行类型提示,请使用Tuple。元组是不可变的,因此您可以确保元组内部具有正确的类型。

from typing import Tuple
my_list = Tuple[str, int, int, str, int]

我认为这更接近我们所需的。使用Union太混乱和随意了。 - A H Bensiali

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接