操作
第5章 型ヒント¶
5.1 型ヒント¶
- 前提: Python は動的型付け言語なので、型解決は実行時に行われ、コーディング時には型付けしない
- ただし、型ヒントをつけることで実行前に静的型チェックを行ったり、IDEでの補助機能への情報を与えることが可能となる
- 型ヒントの書き方
- 基本的な型
# 変数への型付け name: str = "smith" age: int = 41 # 関数での型付け # 引数は変数と同様 # 引数にデフォルト値ありの場合は "変数名: 型名 = 値" # 返り値は "-> 型名" def func(name: str, age: int = 1) -> int: if(name == "smith"): return age else: return 0 - コンテナ型
# 変数への型付け listobj: list = [123, "abc", True] setobj: set = {1, 2, 4, 8, 16} dictobj: dict = {"one": 1, "two": 2} tupleobj: tuple = (123, "abc", True) # 変数への型付け (要素の型) listobj: list[str] = ["123", "abc", "True"] setobj: set[int] = {1, 2, 4, 8, 16} dictobj: dict[str, int] = {"one": 1, "two": 2} tupleobj: tuple[int, str, bool] = (123, "abc", True) # tuple は全要素の型を指定 tupleobj_err: tuple[str] = ("123", "abc") # エラー tupleobj_same: tuple[str, ...] = ("123", "abc", "True") # 全部同じ型ならこの書き方が可能 - ユーザ定義クラス
- 他のオブジェクト指向言語と同様に、定義済みクラスを型として扱える
# book_dataclass.py from dataclasses import dataclass @dataclass class Book: name: str author: str price: int# book_typehint.py from operator import attrgetter from book_dataclass import Book def lowest_price_book(book_list: list[Book]) -> Book: return sorted(book_list, key=attrgetter("price"))[0] books: list[Book] = [ Book("ハッカーガイド", "terapyon", 2992), Book("ゼロから", "tekanori", 3200), Book("スタートブック", "shingo", 2750) ] value_book: Book = lowest_price_book(books) print(value_book)> python .\book_typehint.py Book(name='スタートブック', author='shingo', price=2750)
- 他のオブジェクト指向言語と同様に、定義済みクラスを型として扱える
- 基本的な型
- typing モジュールによる型ヒント
-
特殊な型付けが可能
型 説明 Union 複数指定し、いずれかの型 Optional 指定の型か、None Literal 指定したいずれかの値 Any 任意の型 TypeValueTypeVar型変数の定義 TypedDict 辞書のキー(str)と、値の型を指定 from typing import Union, Optional uniontype: Union[int, str] = 10 uniontype = "ten" opttype: Optional[bool] = True opttype = None # Python3.10 以降の新しい書き方 (typing モジュールインポート不要) uniontype2: int | str = 10 uniontype2 = "ten" opttype2: bool | None = True opttype2 = Nonefrom typing import Literal, Any, TypeVar, TypedDict littype: Literal["Shizuoka", "Nagoya"] = "Shizuoka" littype = "Nagoya" littype = "Tokyo" # NG user_input: Any = utilvalud(args) # 型付け無しの関数返り値を受け取る # TypeVar T = TypeVar("T") # mypy で試したところ、変数と TypeVar() の第1引数は揃えないとダメらしい def reflect(arg: T) -> T: return arg # TypedDict class BookDict(TypedDict): name: str author: str price: int fav_book: BookDict = {"name": "スタートブック", "author": "shingo", "price": 2750}
-
5.2 静的型チェックを行う - mypy (※試験範囲外)¶
型ヒントを用いて静的型チェックを行うツール mypy
- 型ヒントに違反している内容を検知してエラーを出力するツール
- エラーの例
# mypy_check.py # 変数の型NG name: str = 123 age: int = "42" favorite: list = {"study": "AWS", "food": "Curry"} # 関数の返り値型NG def greeting(name: str) -> int: return f"Hi, {name}" # 関数の引数型NG greeting(123)> mypy .\mypy_check.py mypy_check.py:2: error: Incompatible types in assignment (expression has type "int", variable has type "str") [assignment] mypy_check.py:3: error: Incompatible types in assignment (expression has type "str", variable has type "int") [assignment] mypy_check.py:4: error: Incompatible types in assignment (expression has type "dict[str, str]", variable has type "list[Any]") [assignment] mypy_check.py:8: error: Incompatible return value type (got "str", expected "int") [return-value] mypy_check.py:11: error: Argument 1 to "greeting" has incompatible type "int"; expected "str" [arg-type] Found 5 errors in 1 file (checked 1 source file) - 修正後
name: str = "smith" age: int = 41 favorite: list = ["AWS", "Curry"] def greeting(name: str) -> str: return f"Hi, {name}" greeting("Tatsuya")> mypy .\mypy_check_ok.py Success: no issues found in 1 source file
- エラーの例
- オプション指定
- コマンドオプション、設定ファイルのどちらかで指定
- ※コマンドオプションと設定ファイル内の記述が、ハイフンとアンダースコアで異なる
- (例) コマンドオプション
--disallow-any-generics - (例) 設定ファイル
disallow_any_generics = True
- 代表的なオプション
オプション 説明 disallow_any_generics コンテナーの要素の型が無いことを禁止 disallow_untyped_defs 型が無い関数定義を禁止 disallow_untyped_calls 「型が無い関数」の呼び出しを禁止 warn_unused_ignores 「# type: ignore」がある場合に警告 warn_return_any 型が無い変数を返す場合に警告 check_untyped_defs 型が無い関数の内部の型をチェック - 除外に関するオプション
オプション 設定値 説明 follow_imports normal,
silent,
skip,
errorインポートしたモジュールをチェックするルールの指定 ignore_missing_imports bool インポートしたモジュールに関するエラーを抑制する(デフォルト False) exclude 正規表現 除外ファイル・ディレクトリを正規表現で指定 - 設定ファイル
- プロジェクトディレクトリ直下に配置
mypy.ini.mypy.inipyproject.tomlsetup.cfg
- ユーザディレクトリ配置
$XDG_CONFIG_HOME/mypy/config~/.config/mypy/config
- 書き方
[mypy] follow_imports = silent disallow_any_generics = True warn_return_any = True- 特定モジュールでのみ有効化なオプションの設定は
[mypy-モジュール名]セクションに記述[mypy-aiohttp.*] follow_imports = False [mypy-sqlalchemy.*] ignore_missing_imports = True
- 特定モジュールでのみ有効化なオプションの設定は
- プロジェクトディレクトリ直下に配置
- コマンドオプション、設定ファイルのどちらかで指定
- よくあるエラーと対処
- 型ヒントを定義しているスタブファイル (
*.pyi形式の外部ファイル) が無い場合にエラーが出る場合がある- サードパーティのライブラリは、型定義リポジトリの typeshed にスタブファイルがあるかも
-
typeshed のスタブファイルインストールは
mypy --install-typesで行える -
typeshed にスタブファイルが無い場合
- ライブラリのアップデート
- ライブラリのスタブファイルの確認
- ライブラリを mypy チェックから除外する
import example # type: ignore
- 型ヒントを定義しているスタブファイル (
Tatsuya ISHIGAKI さんが5ヶ月前に更新 · 2件の履歴