はじめに
この手法はそもそも非推奨かもしれないし、もっといい方法があるかもしれないが"なんか知らんけどとりあえずやりたいことはできた"のでまとめておく。
推奨される方法等があれば教えてくださると助かります。
経緯(文句)
個人的にぺちぺちコーディングをしているときに、クラスオブジェクトを引数に渡したりしてこねくり回すことがある。
クラスオブジェクトを引数に渡したりしたときに、デフォだと型がanyになって、インテリセンス(入力補助とかF12で宣言元に飛ぶとか)が効かなくなる。
入力補助はともかく、F12で宣言元に飛べなくなるのはつらいって言うのは共感していただけると思う。
ここでインテリセンスを有効にするためには型ヒントをつけてあげる必要がある。
自分が作った別ファイルに定義しているクラスだと、型ヒントをつけるためだけに行うインポートで、やれ上位のパッケージだ、やれ循環参照だと実行時に余計なおせっかいを焼いて来ることがある。
あくまでインテリセンスを使うためだけにインポートするのであって、実行時にはインポートしなくていいのに、実行エラー出されてもなぁと言うことで、それを回避する方法を見つけた。
やり方
TYPE_CHECKING
をインポートして、TYPE_CHECKING == True
のときだけインポートさせる。
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from ..my_class_a import MyClassA
class MyClassB:
def __init__(self, class_a: MyClassA):
self.class_a = class_a
def func_b(self):
return self.class_a.func_a()
TYPE_CHECKING は、型チェッカーがコードを分析するときにのみ True になるみたい。
これにより、実行時にはインポートが行われず、型チェック時にのみインポートしているように見せることができるようだ。
これでVSCodeのインテリセンスを活用しつつ、実動作時にはインポートさせないことで循環インポートとか本来考えなくていい問題を避けることできる、と。
おまけ
ちなみにannotationsをインポートしない場合、TYPE_CHECKINGでインポートしたクラスはクウォートで囲う必要があるみたい。
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from ..my_class_a import MyClassA
class MyClassB:
def __init__(self, class_a: "MyClassA"):
self.class_a = class_a
def func_b(self):
return self.class_a.func_a()