私は現在、楽しみと言語の練習のために Python 線形代数モジュールを作成中です。最近、次のような型注釈をモジュールに追加しようとしました。
class Vector:
# Various irrelevant implementation details
def __add__(self, other: Vector) -> Vector:
# More implementation details....
しかし、これをインポートしようとすると、 が吐き出されますNameError: Name 'Vector' is not defined
。この質問は、すでに回答されていることを承知しています。ここしかし、それは私の状況に完全な答えを与えているようには思えません。
知りたいこと:
- このファイルでクラスを文字通り定義しました。名前が定義されていないと表示されるのはなぜですか?
Vector
を注釈として使用できるような方法で定義するにはどうすればよいですかtype
?
ベストアンサー1
前方宣言があり、関数(メソッドとしてバインドされる)が作成されます前にクラスは実行されていないため、名前はVector
まだ存在していません。クラス本体がすべて実行された場合にのみ、Python はオブジェクトを作成し、それにclass
名前をバインドできます。Vector
代わりに名前を含む文字列を使用します。
class Vector:
# Various irrelevant implementation details
def __add__(self, other: 'Vector') -> 'Vector':
# More implementation details....
これは、IDE が宣言を認識する方法には影響しません。文字列はモジュール全体がロードされると検索され、現在のコンテキストで有効な Python 式として解決されます。モジュールVector
全体がロードされるとクラスが存在するため、文字列は'Vector'
クラス オブジェクトに適切に変換できます。
以下も参照前方参照の仕様:
型ヒントにまだ定義されていない名前が含まれている場合、その定義は文字列リテラルとして表現され、後で解決されることがあります。
[...]
文字列リテラルには有効な Python 式が含まれている必要があり、モジュールが完全にロードされるとエラーなしで評価される必要があります。
Python 3.7 以降では、モジュールfrom __future__ import annotations
の先頭にディレクティブを追加することで、特定のモジュール内のすべてのアノテーションをフォワードアノテーションのように動作させることができます (文字列リテラルで囲む必要はありません)。これは元々 Python 3.10 以降でデフォルトになる予定でしたが、この決定は無期限に延期されました。PEP 563 --注釈の評価の延期詳細については、外アノテーションの場合でも、たとえば型エイリアス (Python に関する限り、これは通常の変数割り当てです) などで、前方参照構文 (文字列リテラル) を使用する必要がある場合があります。