1

クラス B と C はどちらも基本クラス A から派生し、どちらも A のメソッド test() をオーバーライドしません。B は A と同じモジュールで定義されています。C は別のモジュールで定義されています。B.test() を呼び出すと「hello」と表示されるのに、C.test() を呼び出すと失敗するのはなぜですか? どちらの呼び出しも A.test() を実行することになるので、mod1 の名前空間でシンボル「メッセージ」を解決できるはずではありませんか?

また、何も見つけることができなかったので、この動作がどこに文書化されているかについてのヒントを喜んで受け取ります. C.test() が呼び出されたときに名前はどのように解決され、「メッセージ」を名前空間の 1 つに何らかの方法で注入できますか?

FWIW、私がインスタンス変数を使用していない理由 (例: set A.message = "hello") は、「グローバル」シングルトン オブジェクトにアクセスしたいので、明示的な参照先を持たせたくないためです。他のすべてのオブジェクト。

mod1.py:

import mod2

class A(object):
  def test(self):
    print message

class B(A):
  pass

if __name__ == "__main__":
  message = "hello"
  A().test()
  B().test()
  mod2.C().test()

mod2.py:

import mod1

class C(mod1.A):
  pass

出力は次のとおりです。

$ python mod1.py 
hello
hello
Traceback (most recent call last):
  File "mod1.py", line 14, in <module>
    mod2.C().test()
  File "mod1.py", line 5, in test
    print message
NameError: global name 'message' is not defined

どうもありがとう!

4

2 に答える 2

2

EOL は正しいです。プログラムの「メイン」部分を新しいファイル mod3.py に移動すると、実際に機能します。

http://bytebaker.com/2008/07/30/python-namespaces/は、この問題をさらに明確にします。

私の最初の質問では、mod1.py がスクリプトとして実行されているため、変数がモジュールの名前空間messageに格納されていることがわかりました。__main__mod2 は mod1 をインポートしますが、変数が存在しない別mod1の名前空間を取得します。次のコード スニペットは、 の名前空間にmessage書き込んでいる様子をより明確に示しており(実際にこれを行うことをお勧めしません)、期待どおりの動作を引き起こしています。messagemod1

import sys

class A(object):
  def test(self):
    print message

class B(A):
  pass

if __name__ == "__main__":
  import mod2
  message = "hello"
  sys.modules["mod1"].message = message
  A().test()
  B().test()
  mod2.C().test()

EOLが示唆するように、プログラムの「メイン」部分を別のモジュールに移動するか、実行するのが最善の現実的な修正だと思います。

class A(object):
  def test(self):
    print message

class B(A):
  pass

def main():
  global message
  message = "hello"
  A().test()
  B().test()

  # resolve circular import by importing in local scope
  import mod2
  mod2.C().test()

if __name__ == "__main__":
  # break into mod1 namespace from __main__ namespace
  import mod1
  mod1.main()
于 2013-03-31T13:09:57.547 に答える