PythonのType Hintを使ってますか?
最初は苦痛でしか無かったのですが、最近、意図通り使えるようになってきた。
Type Hint使う理由(利点)
- 実行前にエラーがわかり、時間節約
- 思い違いの論理エラーを早くに検出し、時間無駄にしない。
- 改てコード見直した時、コード内容を思い起こしやすい。
Type Hintという結論は良さそう
- 型厳密性が高い言語の方がコンパイルした時の早いじゃないの?、と思ってますし、きっとそうでしょう。ただし、静的型付に比べ、型のstrict性が無がないのでPythonicな書き方を維持できていると思う。
- annotationのおかげで、Cythonの型指定も楽になりました。(Pure Pythonモードなので20-50%の向上しか無いそうですが。)
# CythonのAnnonationを使った例
@cython.cdef
def main(a:cython.int):
...
Type Hintが誤解する箇所の対処方法
書きかけです。優先度が高い情報から記載
可読性が高い書き方へ移行
- 古いPythonを使わないといけない時に便利。下記おまじないを書くとPy3.9以降の記法が適用されるみたい
from __future__ import annotations
例えば、
-
typing.Union[int,float]
はint|float
と書ける -
typing.List[int]
もlist[int]
とかける
SQLAlchemyの場合
SQLAlchemyのobjの型補完
下記でうまくいく?エラーで解析できてないだけ?
自動解決されてないので、型を記す。例:registration_datetime:datetime.datetime= Column(DateTime)
- SQLAlchemyはstubがあるけど効かない。どう使うのだろう...import?
- sessionやengineのTypeHint。これをするとPyCharmでは、メソッド候補がホバーされる。
connection_string: str = "sqlite:///:memory:"
engine = create_engine(connection_string)
session = Session(bind=engine)
print(type(engine)) # sqlalchemy.engine.base.Engine
print(type(session)) # sqlalchemy.orm.session.Session
SQLAlchemyのデータ型に対するTypeHintの書き方。
reg_dtt: sqlalchemy.Mapped[datetime.datetime] = sa.Column(sa.DateTime, nullable=False)
上記の通りMapped
で型指定すると、下記通りbetweenでMyPy由来のエラーでない。確認PyCharm2021.1.MyPy0.951.
MyTable.reg_dtt.between(start, end))
Noneから初期化されている事を示す / 型が適切である事を示す。
- assertと併用する
assert 変数 is not None, "変数は初期化されてない"
castを使う
mypyは異なるvenvの物を利用しない
- 結果が正確でなくなるから。おそらく、同venvのパッケージを解析する方が正確なのだろう。
- PyCharmで、高速化を期待してmypyをdaemonとして登録したが、異なるvenvのmypyでは正確ではない事に気づいた。
stub/typesパッケージのインスト
- これらパッケージを入れると、型やら記述された.pyiファイルがインストールされて、IDEなどで型情報が補完されるらしい
- 例
-
wearepal/data-science-types
- Mypy type stubs for NumPy, pandas, and Matplotlib
-
sqlalchemy-stub
2. どちらを使う方がいいのかなsqlalchemy2-stubs
-
wearepal/data-science-types
enum.auto
下記で上手くいく?
var : Enum型Class名|str