2

あいまいなタイトルを失礼します。誰か提案があれば教えてください!また、より適切なタグでタグを付け直してください。

問題

インポートされたクラスのインスタンスが、インポーターのスコープ(グローバル、ローカル)内のものを表示できるようにしたい。ここで機能している正確なメカニズムがわからないため、単語よりもスニペットを使用して説明することができます。

## File 1
def f1():  print "go f1!"

class C1(object):
    def do_eval(self,x):  # maybe this should be do_evil, given what happens
        print "evaling"
        eval(x)
        eval(x,globals(),locals())

次に、反復セッションからこのコードを実行します。NameErrors

## interactive
class C2(object):
    def do_eval(self,x):  # maybe this should be do_evil, given what happens
        print "evaling"
        eval(x)
        eval(x,globals(),locals())

def f2():
    print "go f2!"

from file1 import C1
import file1

C1().do_eval('file1.f1()')
C1().do_eval('f1()')
C1().do_eval('f2()')

file1.C1().do_eval('file1.f1()')
file1.C1().do_eval('f1()')
file1.C1().do_eval('f2()')

C2().do_eval('f2()')
C2().do_eval('file1.f1()')
C2().do_eval('f1()')

この種のタスクに共通のイディオム/パターンはありますか?私は間違った木を完全に吠えていますか?

4

2 に答える 2

2

この例では、関数をオブジェクトとして のメソッドに渡すだけですC1

>>> class C1(object):
>>>    def eval(self, x):
>>>        x()
>>>
>>> def f2(): print "go f2"
>>> c = C1()
>>> c.eval(f2)
go f2

Python では、関数とクラスを他のメソッドに渡し、そこで呼び出し/作成できます。

実際にコード文字列を評価したい場合は、Thomas が既に述べたように、環境を指定する必要があります。

上記のモジュールは、わずかに変更されています。

## File 1
def f1():  print "go f1!"

class C1(object):
    def do_eval(self, x, e_globals = globals(), e_locals = locals()):
        eval(x, e_globals, e_locals)

さて、インタラクティブインタープリターで:

>>> def f2():
>>>    print "go f2!"
>>> from file1 import *    # 1
>>> C1().do_eval("f2()")   # 2
NameError: name 'f2' is not defined

>>> C1().do_eval("f2()", globals(), locals()) #3
go f2!
>>> C1().do_eval("f1()", globals(), locals()) #4
go f1!

いくつかの注釈

  1. ここでは、すべてのオブジェクトfile1をこのモジュールの名前空間に挿入します
  2. f2の名前空間にないfile1ため、NameError
  3. これで環境を明示的に渡し、コードを評価できるようになりました
  4. f1インポートしたため、このモジュールの名前空間にあります

編集: の環境を明示的に渡す方法に関するコード サンプルを追加しましたeval

于 2008-09-22T20:32:17.863 に答える
1

メソッドやクラス本体と同様に、関数は常に定義されているスコープで実行されます。それらが別のスコープで実行されることはありません。インポートは別の割り当てステートメントにすぎず、Python ではすべてが参照であるため、関数、クラス、およびモジュールは、インポート先を認識していません。

使用する「環境」を明示的に渡すか、スタック ハッカーを使用して呼び出し元の名前空間にアクセスします。前者は、後者ほど実装に依存せず、壊れやすいため、後者よりもはるかに好まれます。

同様のことをしようとする string.Template クラスを見たいと思うかもしれません。

于 2008-09-22T19:58:10.813 に答える