pythonは動的に型付けされるので、もちろん次のようなことができます:
def f(x):
return 2 if x else "s"
しかし、これはpythonが実際に使用されることを意図していた方法ですか?言い換えると、たとえば、ユニオンタイプは、ラケットで行うような意味で存在しますか?または、次のように使用するだけです。
def f(x):
if x:
return "s"
私たちが必要とする唯一の「和集合」はNoneであるところですか?
ユニオンタイピングは、オブジェクトが複数のタイプの1つ(あなたの場合はint
またはstr
、または他のタイプ)を返すことができることを宣言する必要があるため、静的に型付けされた言語がある場合にのみ必要です例str
またはNoneType
)。
Pythonはobjectsのみを扱うため、「ユニオンタイプ」を考慮する必要すらありません。 Python関数は返されるものを返します。プログラマが異なる結果に対して異なる型を返したい場合は、それが選択です。選択はアーキテクチャの選択であり、Pythonインタプリタに違いはありません(したがって、ここでは「ベンチマーク」するものはありません)。
Python 3.5では、オプションのタイプhintsを作成するための標準が導入されており、その標準には Union[...]
および Optional[...]
アノテーション。
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 /エディターレベルの構文チェックを有効にすることができます。
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
もちろん、これらのアプローチにはすべて、さまざまな欠点があります。
@MartijnPietersの回答に追加:
しかし、pythonは実際に使用することを意図した方法ですか?
Paramに応じて異なる型を返すことは、どの言語でも決して良い習慣ではありません。これにより、コードのテスト、保守、および拡張が非常に困難になり、IMHOはアンチパターンです(ただし、もちろん必要な悪)。結果は、少なくとも共通のインターフェースを持つことによって関連付けられる必要があります。
union
がCに導入された唯一の理由は、パフォーマンスの向上によるものでした。しかし、Pythonでは、言語の動的な性質のため、このパフォーマンス向上はありません(Martijnが気づいたように)。実際にunion
を導入すると、union
のサイズは常にPythonはCのようなunion
を決して持ちません。