1

次のコードを検討してください。

GLOBAL_VARIABLE = 1

def someFunction():
    nonLocalVariable = 2

    def anotherFunction():
        localVariable = 3

        class LocalClass(object):
            __metaclass__ = MyMetaClass
            __customCode = """
                    GLOBAL_VARIABLE + nonLocalVariable + localVariable
                """

    anotherFunction()

someFunction()

私は、プロパティMyMetaClassの内容に基づいてクラスのメソッドを生成するメタクラスの実装者です。 Python式を含めることができるので、で言及されている変数名が、通常のPythonメソッドで定義されている同じ変数名と同じオブジェクトを参照していることを確認したいと思います。__customCode__customCode__customCode

メタクラスが呼び出されると、クラスの内容を含むdictが渡されます。つまり、メタクラスはについて知っています__customCodeが、それはあまり役に立ちません。を使用すると、 ステートメントが実行されてinspect.currentframe(1)いるスタックフレーム、つまり。を取得します。そのスタックフレームには、属性(を含む)と 属性(特にを含む)がありますが、これら2つを合わせても全体像はわかりません。classanotherFunction().f_localslocalVariable.f_globalsGLOBAL_VARIABLE

のスタックフレームanotherFunction()(またはの実装内から取得できるその他のもの)を考えると、存在する名前空間、およびグローバル名前空間とローカル名前空間の間にネストされた他の名前空間をMyMetaClassどのように見つけることができますか?nonLocalVariable

私は現在Python2.7を使用していますが、Python 3.xで答えが異なる場合は、それも知っておくとよいでしょう。

4

1 に答える 1

4

locals()and構造とは別にglobals()、コンパイラは、a) 割り当てられていないローカル変数、および b) スコープ変数 (Python 3.x では、nonlocalキーワードと同様に、そのような変数にも割り当てることができるキーワードが追加されていますglobal)。

あなたの特定のケースでは、そのような変数はありません。ネストされたコードはnonLocalVariable;を参照していません。anotherFunctionその変数が実際に使用された場合、または実際に使用された場合にのみLocalClass、Python コンパイラ (バイト コンパイル時に) が必要な構造を追加してnonLocalVariable、スコープから引き出すことができます。

ネストされたセットアップの例を次に示します。

>>> def foo(x):
...     y = None
...     def bar():
...         return x
...     return bar
... 
>>> bar = foo('spam')
>>> foo.__code__.co_cellvars
('x',)
>>> bar.__code__.co_freevars
('x',)
>>> dir(bar.func_closure[0])
['__class__', '__cmp__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'cell_contents']
>>> bar.func_closure[0].cell_contents
'spam'

foocodeobject がリストにどのようにリストxされているかco_cellvars、および の codeobject がbarxリストされていることに注意してくださいco_freevars。使用しないため、どちらにも記載されていyませbarbar関数への参照には、作成時にスコープによって指定された現在の値をfunc_closure保持する構造体があります。Code オブジェクトは、関数のバイトコードを保持します。それらはコンパイル時に作成されます。タプルは、および構造体に基づいて実行時に作成されます。xbarfunc_closurefreevarscellvars

これはコンパイル時に発生するため、このようなスコープ変数への参照を動的に作成することは、せいぜいトリッキーです。この場合、スコープ変数の使用をサポートすることさえ気にしません。

于 2013-01-04T13:47:00.657 に答える