0

私は実際に新しいローカルを作成したいと考えています。疑わしいと思われるかもしれませんが、これには良い使用例があると思います。基本的に私の問題は、卵を印刷しようとすると、このコードが「NameError: global name 'eggs' is not defined」をスローすることです。

def f():
    import inspect
    frame_who_called = inspect.stack()[1][0]
    frame_who_called.f_locals['eggs'] = 123

def g():
    f()
    print(eggs)

g()

この古いものを見つけました: http://mail.python.org/pipermail/python-dev/2005-January/051018.html

つまり、ctypes を使用してシークレット関数を呼び出すことができる可能性がありますが、値の更新についてのみ話しました。しかし、もっと簡単な方法があるのではないでしょうか?

4

3 に答える 3

3

あなたのユースケースについて非常に興味があります。一体なぜ、単に次のようなことをするのではなく、発信者のフレームに新しいローカルを突っ込もうとしているのですか:

def f():
    return 123

def g():
    eggs = f()
    print(eggs)

結局、好きなだけ値を持つタプルを返すことができます:

def f():
    return 123, 456, 789

def g():
    eggs, ham, bacon = f()
    print(eggs, ham, bacon)
于 2009-10-07T21:47:27.683 に答える
2

Greg Hewgill が質問に対するコメントで述べたように、Python 3 での変更に関する別の質問localsに回答しました。ここで少し要約します。

この問題については、Python 3 のバグ リストに投稿があります。Python 3 のマニュアルでは、あまり文書化されていません。Python 3 では、Python 2 のような辞書ではなく、ローカル変数に配列を使用します。利点は、ローカル変数のルックアップ時間が短縮されることです (Lua もこれを行います)。基本的に、配列は「バイトコードのコンパイル時」に定義され、実行時に変更することはできません。

これが Python 3 で機能しない (そしておそらく機能しない) 理由の詳細については、バグ リストの Georg Brandl の投稿の最後の段落を特に参照してください。

于 2009-10-08T00:32:52.657 に答える
1

Python 2.* では、ローカルの通常の最適化を無効にすることで、このようなコードを機能させることができます。

>>> def g():
...   exec 'pass'
...   f()
...   print(eggs)

ステートメントが存在すると、execPython 2gは完全に最適化されていない方法でコンパイルされるため、ローカルは通常の配列ではなく辞書になります。(パフォーマンスへの影響はかなり大きくなる可能性があります)。

この「最適化解除」は Python 3 には存在しません。ここで、execはもはやステートメントではありません (キーワードでさえなく、ただの関数です) -- 後に括弧を付けても役に立ちません...:

>>> def x():
...   exec('a=23')
...   print(a)
... 
>>> x()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in x
NameError: global name 'a' is not defined
>>> 

つまり、 -time (つまり、コンパイラが関数本体をバイトコードに変換するためのパスを行ったとき) にexec認識されていなかった "ローカルを作成" することさえできなくなります。def

あなたの最善の策はあきらめることです。2番目に良いのは、f関数に新しい名前を呼び出し元の名前に挿入させることですglobals-結局のところ、それらはまだdictです。

于 2009-10-08T01:47:40.713 に答える