web-dev-qa-db-ja.com

共用体型は実際にPythonに存在しますか?

pythonは動的に型付けされるので、もちろん次のようなことができます:

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

しかし、これはpythonが実際に使用されることを意図していた方法ですか?言い換えると、たとえば、ユニオンタイプは、ラケットで行うような意味で存在しますか?または、次のように使用するだけです。

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

私たちが必要とする唯一の「和集合」はNoneであるところですか?

13
Lana

ユニオンタイピングは、オブジェクトが複数のタイプの1つ(あなたの場合はintまたはstr、または他のタイプ)を返すことができることを宣言する必要があるため、静的に型付けされた言語がある場合にのみ必要です例strまたはNoneType)。

Pythonはobjectsのみを扱うため、「ユニオンタイプ」を考慮する必要すらありません。 Python関数は返されるものを返します。プログラマが異なる結果に対して異なる型を返したい場合は、それが選択です。選択はアーキテクチャの選択であり、Pythonインタプリタに違いはありません(したがって、ここでは「ベンチマーク」するものはありません)。

Python 3.5では、オプションのタイプhintsを作成するための標準が導入されており、その標準には Union[...] および Optional[...] アノテーション。

19
Martijn Pieters

Pythonは動的に型付けされた言語にすぎないため、型自体は存在しませんが、新しいPythonバージョンでは、Union Typeが タイプHinting

from typing import Union,TypeVar

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

これを使用してコードに注釈を付け、IDE /エディターレベルの構文チェックを有効にすることができます。

10
Sajuuk

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 module

もちろん、これらのアプローチにはすべて、さまざまな欠点があります。

2
Mateen Ulhaq

@MartijnPietersの回答に追加:

しかし、pythonは実際に使用することを意図した方法ですか?

Paramに応じて異なる型を返すことは、どの言語でも決して良い習慣ではありません。これにより、コードのテスト、保守、および拡張が非常に困難になり、IMHOはアンチパターンです(ただし、もちろん必要な悪)。結果は、少なくとも共通のインターフェースを持つことによって関連付けられる必要があります。

unionがCに導入された唯一の理由は、パフォーマンスの向上によるものでした。しかし、Pythonでは、言語の動的な性質のため、このパフォーマンス向上はありません(Martijnが気づいたように)。実際にunionを導入すると、unionのサイズは常にPythonはCのようなunionを決して持ちません。

2
freakish