59

私は現在、楽しみと言語の練習のために、python 線形代数モジュールの作成に取り組んでいます。私は最近、モジュールに型注釈を追加しようとしました。

class Vector:
     # Various irrelevant implementation details
     def __add__(self, other: Vector) -> Vector:
        # More implementation details....

ただし、これをインポートしようとすると、NameError: Name 'Vector' is not defined. この質問はフォームで既に回答されていることを認めます ここ、しかし、私の状況に対する完全な回答を提供しているようには見えません.

知りたいこと:

  • このファイルで文字通りクラスを定義しました。名前が定義されていないと言うのはなぜですか?
  • Vector注釈に ( として) 使用できるように定義するにはどうすればよいtypeですか?
4

2 に答える 2

80

前方宣言があります。関数 (メソッドとしてバインドされる) はクラスが作成される前に作成されるため、名前Vectorはまだ存在しません。すべてのクラス本体が実行された場合にのみ、Python はclassオブジェクトを作成し、それに名前をバインドできますVector

代わりに、名前に文字列を使用するだけです。

class Vector:
     # Various irrelevant implementation details
     def __add__(self, other: 'Vector') -> 'Vector':
        # More implementation details....

これは、IDE が宣言を認識する方法には影響しません。モジュール全体がロードされると文字列が検索され、現在のコンテキストで有効な Python 式として解決されます。Vectorモジュール全体が読み込まれるとクラスが存在するため、文字列'Vector'を適切にクラス オブジェクトに変換できます。

前方参照の仕様も参照してください。

型ヒントにまだ定義されていない名前が含まれている場合、その定義は文字列リテラルとして表現され、後で解決される場合があります。

[...]

文字列リテラルには有効な Python 式 [...] が含まれている必要があり、モジュールが完全に読み込まれるとエラーなしで評価されます。

from __future__ import annotationsPython 3.7 では、モジュールの先頭にディレクティブを追加することで、特定のモジュール内のすべての注釈を (文字列リテラルで囲むことなく) 前方注釈のように動作させることができます。Python 3.10 以降では、これがデフォルトの動作になりましたPEP 563 -アノテーションの評価の延期を参照してください。注釈の外では、型エイリアス (Python に関する限り、通常の変数割り当て) などで、前方参照構文 (文字列リテラル) を使用する必要があることに注意してください。

于 2016-03-29T14:15:41.107 に答える