联合类型实际上存在于python中吗?

时间:2016-08-09 15:01:15

标签: python types unions dynamic-typing

由于python是动态类型的,当然我们可以这样做:

def f(x):
    return 2 if x else "s"

但是python的实际用途是什么?或换句话说,联盟类型是否存在于他们在球拍中的意义上?或者我们只是这样使用它们:

def f(x):
    if x:
        return "x"

我们需要的唯一“联盟”是否为?

6 个答案:

答案 0 :(得分:15)

只有拥有静态类型语言时才需要进行联合键入,因为您需要声明对象可以返回多种类型之一(在您的情况下为intstr,或者在其他示例strNoneType)。

Python仅处理对象,因此甚至不需要考虑“联合类型”。 Python函数返回它们返回的内容,如果程序员想要为不同的结果返回不同的类型,那么这就是他们的选择。那么选择是一个架构选择,并且对Python解释器没有任何影响(所以这里没有“基准”)。

Python 3.5确实引入了用于创建可选类型提示的标准,该标准包含Union[...]Optional[...]注释。

答案 1 :(得分:9)

类型本身不存在,因为Python只是一种动态类型语言,但是,在较新的Python版本中,Union Type是Type Hinting的选项,

from typing import Union,TypeVar

T = TypeVar('T')
def f(x: T) -> Union[str, None]:
    if x:
        return "x"

您可以使用它来注释您的代码,从而启用IDE /编辑器级语法检查。

答案 2 :(得分:3)

以前的答案没有解决的一个用例是从预先存在的类型构建联合类型,并且isinstance() 认为预先存在的类型的任何实例都是联合类型。

Python 通过抽象基类支持这一点。例如:

>>> import abc
>>> class IntOrString(abc.ABC): pass
... 
>>> IntOrString.register(int)
<class 'int'>
>>> IntOrString.register(str)
<class 'str'>

现在可以将 intstr 视为 IntOrString 的子类:

>>> issubclass(int, IntOrString)
True
>>> isinstance(42, IntOrString)
True
>>> isinstance("answer", IntOrString)
True

答案 3 :(得分:2)

添加到@MartijnPieters回答:

  

但实际上是否打算使用python的方式?

根据参数返回不同的类型从来都不是任何语言的好习惯。这使得测试,维护和扩展代码变得非常困难,而且恕我直言是一种反模式(但当然有时是必要的邪恶)。结果至少应该通过共同的界面来解决。

引入C union的唯一原因是性能提升。但是在Python中,由于语言的动态性,你没有这种性能提升(正如Martijn注意到的那样)。实际上引入union会降低性能,因为union的大小始终是最大成员的大小。因此,Python永远不会像C一样union

答案 4 :(得分:2)

在需要使用Python tagged union/sum type的用例时,有两种选择:

  • 枚举+元组

    from enum import Enum
    Token = Enum('Token', ['Number', 'Operator', 'Identifier', 'Space', 'Expression'])
    
    (Token.Number, 42)                            # int type
    (Token.Operator, '+')                         # str type 1
    (Token.Identifier, 'foo')                     # str type 2
    (Token.Space, )                               # no data
    (Token.Expression, 'lambda', 'x', 'x+x')      # multiple data
    
  • isinstance

    if isinstance(token, int):
        # Number type
    if isinstance(token, str):
        # Identifier type
    
  • sumtypes模块

这些方法当然都有其各种缺点。

答案 5 :(得分:0)

从 Python 3.10 开始,您可以对联合类型使用 | 分隔符。以 What's New In Python 3.10 中的例子为例:

def square(number: int | float) -> int | float:
    return number ** 2

# Instead of 
def square(number: Union[int, float]) -> Union[int, float]:
    return number ** 2

此外,如果您使用的是 Python 3.7+,则可以通过使用 __future__ 包来拥有该功能,但有一些限制:

from __future__ import annotations

# Works in Python 3.7+
def square(number: int | float) -> int | float:
    return number ** 2

# Works only in Python 3.10+
isinstance(3.10, int | float)
numeric = int | float

有关详细信息,请参阅 Union Types documentationPEP 604