Skip to content

Instantly share code, notes, and snippets.

@hotchpotch
Created July 6, 2021 11:34
Show Gist options
  • Save hotchpotch/f0253edcc1d403ffb38740cf2e0ecc74 to your computer and use it in GitHub Desktop.
Save hotchpotch/f0253edcc1d403ffb38740cf2e0ecc74 to your computer and use it in GitHub Desktop.
Python で型ヒントを書く
from __future__ import annotations
from typing import Any, Generic, Optional, TypeVar, Union, cast
from typing_extensions import TypedDict
s: str = "a"
# `:str` と書かなくても型推論される(この場合は自明だが…)
s_type_inference = "あ"
i: int = 1
f: float = 3.14
# 型が違うので型エラー
s + f
s_type_inference + f
l: list[str] = ["あ", "い"]
l.append(100)
d: dict[str, int] = {"a": 1}
d["b"] = 2
d["c"] = "str"
# Union
str_or_int: str | int = 1
# 同じ
str_or_int: Union[str, int] = 1
str_or_int = "あ"
# Optional
str_or_none: str | None = None
# 同じ
str_or_none: Optional[str] = None
def safe_upper(word: str | None) -> str:
# None の可能性があるのでエラー
word.upper()
if word == None:
return ""
# ここではstr型と静的解析され、型エラーにならない
return word.upper()
# 特定の key, value の dict の定義
class UserEntity(TypedDict):
user_id: int
name: str
# 型チェックもされるし補完もされる
user = UserEntity(user_id=1, name="foo")
user_type_error = UserEntity(user_id="1", name="bar")
# 実際はただの dict
print(user.__class__) # => dict
# dict syntaxでの代入もできる
user: UserEntity = {"user_id": 1, "name": "baz"}
user_type_error: UserEntity = {"user_id": "1", "name": "baz"}
# 型変数と制約
T = TypeVar("T", str, int)
# クラスの場合は Generic を使う
class Adder(Generic[T]):
def __init__(self, value: T):
self.value = value
def add(self, n: T):
self.value = self.value + n
def get(self) -> T:
return self.value
# int
int_adder = Adder(3)
int_adder.add(2)
int_adder.get()
# str
str_adder = Adder("add")
str_adder.add("er")
str_adder.get()
str_adder.add(10)
# 関数
def adder_func(a: T, b: T) -> T:
return a + b
int_res = adder_func(1, 2)
str_res = adder_func("foo", "bar")
def adder_func_戻り値が型推論されない(a: T, b: T):
"""
戻り値は T と推論してほしいが…
"""
return a + b
int_res_推論されない = adder_func_戻り値が型推論されない(1, 2)
#%%
# debug 時の型確認
reveal_type(int_res)
reveal_type(str_res)
reveal_type(int_res_推論されない)
"""
# pyright コマンドを実行すると...
demo-1-presentation.py:105:13 - info: Type of "int_res" is "int"
demo-1-presentation.py:106:13 - info: Type of "str_res" is "str"
demo-1-presentation.py:107:13 - info: Type of "int_res_推論されない" is "str* | int*"
"""
#%%
# キャスト
i_any: Any = 1
i = cast(int, i_any)
str_any: Any = "foobar"
i = cast(int, str_any)
# cast は あくまで型ヒントが変わるだけ
# 型ヒントではエラーにならないが、実行時エラー
i.bit_length()
#%%
# 型エラーの強制無視
ten: int = "10"
ten: int = "10" # type: ignore
ten.bit_length() # もちろん実行時エラー
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment