型ヒント関連では、次の機能がPython 3.10で追加されました。
- PEP 604 Allow writing union types as X | Y
- PEP 612 Parameter Specification Variables
- PEP 613 Explicit Type Aliases
- PEP 647 User-Defined Type Guards
まず、PEP 604 Allow writing union types as X | Y から解説します。
|
演算子によるユニオン型の指定¶
Pythonでは、引数にいろいろな種類の値を指定できる関数がめずらしくありません。
例えば、文字列の先頭部分が指定した文字列で始まるかどうかを調べる str.startswith() メソッドには、引数として文字列または文字列のタプルを指定できます。
引数に文字列を指定すると、その文字列で始まる場合には True
を返します。
>>> 'abcdefg'.startswith('abc')
True
>>> 'abcdefg'.startswith('123')
False
タプルを指定すると、その中のいずれかの文字列で始まる場合に True
を返します。
>>> 'abcdefg'.startswith(('123', 'abc', 'αβγ'))
True
このように、startswith()
メソッドの引数には、文字列またはタプルを指定できようになっています。
ユニオン型¶
この引数のように、異なる型の値を使える変数の型ヒントは ユニオン型 として指定します。startswith()
メソッドの引数は、typing.Union を使って、次のように定義できます。
from typing import Union
def startswith(prefix: Union[str, tuple[str, ...]])->bool
...
PEP 604: |
演算子によるユニオン型の指定¶
Pythonではユニオン型がよく使われていますので、いちいち Union
をインポートして指定するのは少々面倒でした。
しかし、PEP 604: Allow writing union types as X | Y では、Union
を使わなくとも、typescriptなどと同じように |
演算子を使って指定できるようになりました。
def startswith(prefix: str | tuple[str, ...])->bool
...
オプショナル型¶
ところで、startswith()
メソッドは、どの文字から比較するか、位置を指定できるようになっています。
開始位置として 3
と指定すると、文字列の3文字目から比較を行います。
>>> 'abc1234'.startswith('abc', 3)
False
開始位置を省略するか、 None
を指定すると文字列の先頭から比較を行います。
>>> 'abc1234'.startswith('abc', None)
True
このように、値を指定するか、省略する場合は None
を指定する というパターンもPythonではよく使われますので、専用の型定義として Optional が用意されています。Optional
を使うと、上記の定義は次のように書けます。
def startswith(prefix:str, start:Optional[int]=None)->bool
...
オプショナル型はユニオン型の特殊な場合で、次のように int
または None
を指定できるユニオン型としても定義できます。
def startswith(prefix:str, start:Union[int, None]=None)->bool
...
|
演算子によるオプショナル型の指定¶
オプショナル型もユニオン型の特殊なケースですので、Python3.10からは同じように |
演算子で書けるようになりました。
def startswith(prefix:str, start:int|None=None)->bool
...
isinstance()/issubclass()での利用¶
従来の typing.Union
や typing.Optional
型は、型アノテーションを指定するためにしか利用できませんでした。 PEP 604
では isinstance()
や issubclass()
にユニオン型を指定できるようになりました。
これまで、オブジェクトが複数の型のどれかに属するかどうかをisinstance()
で調べるときには
>>> isintance(obj, (int, str)) # objが整数か文字列のときはTrue
True
とタプルを使って複数の型を指定していました。
今後は |
演算子を使って
>>> isintance(obj, int|str) # objが整数か文字列のときはTrue
True
と書けるようになりました。