今回は基本的なPythonのTypingについてまとめました。
今回記載するルールをすべて知ってたらTypingでそんなに困ることないと思います。
TypeGuardやLiteralなど応用的なやつは別記事で書いているのでそちらもよかったら見てみてください。
目次
Typingとは?
Pythonでも型を記載することができます。その仕組みがTyping。
PyCharmなどのエディタだと指定したtypingとマッチしないと警告を出してくれたりします。
ただし、実行時にチェックしてくれるわけではないので、あくまでコーディング中のみ使えるようなものです。
それでも指定するとコードの読みやすさや保守性は大幅に向上すると思います。
基本的なTypingの書き方、パッケージ
変数の型はこんな感じ。
変数名: 型 = 値
self.変数名: 型 = 値 # メンバ変数も同じ
関数のType hintはこのようなルールです。
def 関数名(引数名 : 型,....) -> <戻り値の型>:
return ~
ListやDict、Optionalや関数オブジェクトを表すCallableはtypingパッケージのimportが必要です。標準で入っているのでpip installなどは必要ありません。
from typing import List, Callableなどが必要になってきます。
基本的な組み込み型
まずはstr, int, float型。
単純にstr, int, floatを記載するだけ。
ちなみにどの型でも許容する場合はanyを指定する。
def test_func(str_arg: str, int_arg: int, float_arg: float) -> any:
return "test", "hoge"
List, Tuple, Set, Dict型のTyping
まずはListとSet。
List[リスト要素の型]という形式。Setも同様でSet[セット要素の型]。
typingのList, Setをimportする必要がある。
from typing import List, Set
def sum_list(ls: List[int]) -> int:
result = 0
for num in ls:
result += num
return result
set_val: Set[int] = {1, 2, 3, 4, 5, 6}
次にTuple。
Tuple[1つ目の値の型, 2つ目の値の型….]という形式。typingのTupleをimportする必要がある。
from typing import Tuple
# 面積と周囲長を計算する関数
def calc_area_and_perimeter(size: Tuple[int, int]) -> Tuple[int, int]:
return size[0] * size[1], size[0]*2 + size[1]*2
次にDict。
Dict[keyの型, valueの型]という形式。typingのDictをimportする必要がある。
from typing import Dict
key_value: Dict[str, int] = {"aaa": 1, "bbb": 2}
自作ClassのTyping
自作Classは普通にClassを指定するだけ。
また、staticmethodで自身のClassオブジェクトを返したい場合は’Class名’にする必要がある。
class CustomClass:
def __init__(self, a: str):
self.a = a
@staticmethod
def create() -> 'CustomClass':
return CustomClass("from create function.")
custom_class_obj: CustomClass = CustomClass.create()
複数の型を許容する場合 – Union型
Union[許容する型1, 許容する型2,…]といった感じで複数の型を許容することを表すことができる。
from typing import Unionが必要。
from typing import Union, List, Tuple
def return_head_and_tail(arg: Union[str, List: any]) -> Tuple[any, any]:
return arg[0], arg[-1]
return_head_and_tail([1, 2, 3])
return_head_and_tail("hogehoge")
Noneを許容する場合 – Optional型
Noneも許容する型は、Optional[本来期待する型]にすることで表すことができる。
from typing import Optionalが必要。
from typing import Optional
# 引数がNoneであることも考慮した関数
def decorate_str(str_val: Optional[str]) -> str:
if str_val is None:
return "----- no value -----"
return f"----- {str_val} -----"
print(decorate_str("test"))
print(decorate_str(None))
関数オブジェクト・コールバック – Callable型
関数オブジェクトもType hintが可能です。
Callable[[引数1の型, 引数2の型,…], 戻り値の型]というように表せます。
from typing import Callableが必要。
from typing import Callable, List
# リストの隣合う2つの値を何かしら計算して返す
def calc_two_num(ls: List[int], func: Callable[[int, int], int]):
result = []
for i in range(len(ls) - 1):
one_val, two_val = ls[i], ls[i + 1]
calculated_val = func(one_val, two_val)
result.append(calculated_val)
return result
ls = [1, 2, 3, 4, 5]
print(calc_two_num(ls, lambda a, b: a + b))
print(calc_two_num(ls, lambda a, b: a * b))
GeneratorのTyping
GeneratorもType hintが可能です。
Generator[yieldで返す値の型, ?, ?]
Generatorの2,3つ目の型は調べてもよく分からないです。yieldだけなら1つ目の型だけ指定すればいいです。
from typing import Generatorが必要です。
import random
from typing import Generator
def random_int_generator() -> Generator[int, None, None]:
for _ in range(3):
yield random.randint(0, 10)
generator = random_int_generator()
for val in generator:
print(val)