pythonでDocstringを記載し、型定義を行ったサンプル
開発したソースにはDocstringと型定義をするようにしているが、面倒なのか書いている人が少ない気がする。
型定義を書くと便利だと言うために型定義を体験できるサンプルを作ってみた。
動作環境
- python 3.10.6
Docstringとは
Pythonにおけるdocstringとは、関数やクラス、メソッドなどのドキュメンテーションに用いられる文字列のことで、対象の関数やクラスの使い方や仕様、戻り値の型などを記述するために用いられます。
また、型定義にはtypingモジュールを使用します。型定義を書くことで、静的コード解析ツールによるエラー検知や、コード補完の精度向上が期待できます。
以下は、Python3.10.6で動作する、docstringと型定義を用いたサンプルコードです。get_todos_none_type関数はdocstringや型定義がないため、戻り値の詳細が不明なことが確認できます。
サンプルのソースの説明
get_todos_none_type
- Docstringも型定義もなし → JSONが戻ってくるんだなと分かるが詳細不明
get_todos_type_requests_response
- Docstringあり、ResuestsのResponseオブジェクトが戻ってくると分かるので、vscodeでコード補完が効くが中身のデータは詳細不明
get_todos_type_dict
- Docstringに戻ってくる値のサンプルあり、型定義にDict[str, Union[str, int]]とあるのでdict型としてコード補完が効く
get_todos_typeddict
- Docstringに戻ってくる値のサンプルあり、型定義にTypedDictの形式を指定しているためdict型としてのコード補完とキー名についてもコード補完が効く(コード補完も効いてコードが書きやすいが、TypedDictの定義がめんどくさい…)
サンプルソース
- {JSON} Placeholderにアクセスして1件分のデータを取得する
- requestsを利用しているのでpip install requestsをしてください
from typing import Dict, TypedDict, Union import requests def _get_json(id): URL = "https://jsonplaceholder.typicode.com/todos/1" res = requests.get(URL) return res # 何も記載なし def get_todos_none_type(id): res = _get_json(id) return res.json() # docstringと型定義あり オブジェクト def get_todos_type_requests_response(id: int) -> requests.Response: """JSONPlaceholderからidに指定されたTodoを1件分取得して返す Args: id (int): Todoを取得するID Returns: requests.Response: 取得したデータをResponse形式で返す """ res = _get_json(id) return res # dosctringと型定義あり Dictで型定義(key:str, value:str)で詳細はdocstringに記載 def get_todos_type_dict(id: int) -> Dict[str, Union[str, int]]: """JSONPlaceholderからidに指定されたTodoを1件分取得して返す Args: id (int): Todoを取得するID Returns: Dict[str, Union[str, int]]: Todoの1件分のデータを返す Examples: INPUT: id: 1 OUTPUT: { "userId": 1, "id": 1, "title": "delectus aut autem", "completed": false } """ res = _get_json(id) return res.json() # Dict[str, Union[str, int]]としても中身が良くわからないので、厳密に定義する場合の書き方 class Todo(TypedDict): userId: int id: int title: str completed: bool # dosctringと型定義あり TypeDictで指定 def get_todos_typeddict(id: int) -> Todo: """JSONPlaceholderからidに指定されたTodoを1件分取得して返す Args: id (int): Todoを取得するID Returns: Todo: Dict[Todo]形式のデータを返す Examples: INPUT: 1 OUTPUT: { "userId": 1, "id": 1, "title": "delectus aut autem", "completed": false } """ res = _get_json(id) return res.json() def main(): TODO_INT_ID = 1 TOTO_STR_ID = "1" # 型指定なし、レスポンスの型なし # パラメータに型がないので静的コードチェックでエラーにならない res_none = get_todos_none_type(TODO_INT_ID) # resの型が不明な為コードの補完が働かない print(res_none) # 型指定あり、レスポンスの型(object) # 静的コードチェックでSTR型なのでNGになるが、pythonの実行自体はエラーとならない res_response = get_todos_type_requests_response(TOTO_STR_ID) # ← pylanceがエラーを出す # INT型なのでOK res_response = get_todos_type_requests_response(TODO_INT_ID) # resに型があるのでコード補完が利用できる print(res_response.json()) # 型指定あり、レスポンスの型(Dict) res_dict = get_todos_type_dict(TODO_INT_ID) # resにTypedDictの型指定があるのでdictのメソッドの補完とキー名の補完が可能 print(res_dict["userId"]) res_typedict = get_todos_typeddict(TODO_INT_ID) print(res_typedict["completed"]) if __name__ == "__main__": main()