3
class Outer(object):
    class InnerBase(object): _var = {'foo', 'bar'}
    class Derived(InnerBase):
        _var = _var | {'baz'} # NameError: name '_var' is not defined
        _var = InnerBase._var | {'baz'} #  name 'InnerBase' is not defined
        _var = Outer.InnerBase._var | {'baz'} #  free variable 'Outer'
        # referenced before assignment in enclosing scope

_var を移動しOuterても役に立ちません。モジュール スコープ内に移動しても機能しますが、クラスを持つ目的が無効になります。では、どうすればいいのでしょうか?

編集:Javaから来ているので、クラスのスコープルールは私にとって頭の痛い問題です-ブリーフィングをいただければ幸いです。これはうまくいきます:

    class Derived(InnerBase): pass
    Derived._var = InnerBase._var | {'baz'}

しかし、それはエレガンスの頂点ではありません。

関連:ネストされたクラスのスコープ? - ただし、ここでは (アウター タイプではなく) 特に親クラスにアクセスしたい

EDIT2:私が実際に求めているのは、の_var = __class__._varような構文(またはハック)、またはそれが存在しない理由についての説明です

4

3 に答える 3

3

Python は、クラス ステートメントを囲む中で名前を検索することはありません。Mark Lutz は、Python の紹介 ( Learning Python )でスコープを要約するために頭字語LEGBを使用しています。クラス ステートメントは、このスコープ リストから除外されます。Python は、クラス ステートメントを囲んでいる名前を検索しません。def

1 つの解決策は、クラスのネストを解除することです。Python では、ネストされていないクラスを使用することが、その単純さのためにしばしば好まれます。しかし、もちろん、クラスをネストする正当な理由もあります。なぜネストしたのInnerBaseですか?Java の経験から、そのクラスをネストしたのではないでしょうか。次のことも同様に機能しますか?

class InnerBase(object):
    _var = {'foo', 'bar'}

class Derived(InnerBase):
    _var = InnerBase._var | {'baz'}

>>> Derived._var
set(['baz', 'foo', 'bar'])

これら 2 つのクラス ステートメントを別のクラス ステートメントの下にネストすると、これらは名前検索から除外されます。これは、それらがより大きなクラス ステートメントの一部になり、さまざまなスコープの検索から除外されるためです。

于 2015-04-25T16:21:38.037 に答える
2

classステートメントをバイパスして、への明示的な呼び出しを使用できtypeます。

class Outer(object):
    class InnerBase(object): _var = {'foo', 'bar'}
    Derived = type('Derived',
                   (InnerBase,),
                   {'_var': InnerBase._var | {'baz'}}
                  )

これは、 がを定義するステートメントDerived._varの代入ステートメントを介して設定されていないため機能しますが、それ自体と同じ環境で作成した辞書からインポートされます。classDerivedInnerBase

于 2015-04-25T17:00:46.813 に答える
-1

メソッドに入れると動作します。

    def __init__(self):
        _var = Outer.InnerBase._var | {'baz'}
        #_var = super(Outer.Derived, self)._var | {'baz'}    # or with super
        print(_var)

だから私の印象は、それはすべて初期化に関するものだということです。

于 2015-04-25T13:41:35.923 に答える