Pythonのネストされたクラスのスコープを理解しようとしています。コードの例を次に示します。
class OuterClass:
outer_var = 1
class InnerClass:
inner_var = outer_var
クラスの作成が完了せず、エラーが表示されます。
<type 'exceptions.NameError'>: name 'outer_var' is not defined
inner_var = Outerclass.outer_var
を試しても機能しません。私は得る:
<type 'exceptions.NameError'>: name 'OuterClass' is not defined
InnerClass
から静的outer_var
にアクセスしようとしています。
これを行う方法はありますか?
class Outer(object):
outer_var = 1
class Inner(object):
@property
def inner_var(self):
return Outer.outer_var
これは、他の言語で同様のことが機能するのとまったく同じではなく、outer_var
へのアクセスをスコープする代わりにグローバルルックアップを使用します。 (名前Outer
がバインドされているオブジェクトを変更すると、このコードは次に実行されるときにそのオブジェクトを使用します。)
outer_var
は実際にはインスタンス属性であるため、代わりにすべてのInner
オブジェクトにOuter
への参照を持たせたい場合:
class Outer(object):
def __init__(self):
self.outer_var = 1
def get_inner(self):
return self.Inner(self)
# "self.Inner" is because Inner is a class attribute of this class
# "Outer.Inner" would also work, or move Inner to global scope
# and then just use "Inner"
class Inner(object):
def __init__(self, outer):
self.outer = outer
@property
def inner_var(self):
return self.outer.outer_var
Pythonでクラスをネストすることはやや一般的ではなく、クラス間の特別な関係が自動的に暗示されるわけではないことに注意してください。ネストしない方がいいでしょう。 (必要に応じて、Outer
のクラス属性をInner
に設定することもできます。)
私はあなたが簡単にできると思う:
class OuterClass:
outer_var = 1
class InnerClass:
pass
InnerClass.inner_var = outer_var
あなたが遭遇した問題はこれによるものです:
ブロックは、1つの単位として実行されるPythonプログラムテキストです。ブロックは次のとおりです。モジュール、関数本体、およびクラス定義。
(...)
スコープは、ブロック内の名前の可視性を定義します。
(...)
クラスブロックで定義された名前の範囲は、クラスブロックに制限されています。メソッドのコードブロックには拡張されません。関数スコープを使用して実装されるため、これにはジェネレーター式が含まれます。これは、以下が失敗することを意味します。class A: a = 42 b = list(a + i for i in range(10))
http://docs.python.org/reference/executionmodel.html#naming-and-binding
上記の意味:
関数本体はコードブロックであり、メソッドは関数です。クラス定義に存在する関数本体から定義された名前は、関数本体に拡張されません。
あなたの場合、これを言い換えます:
クラス定義はコードブロックであり、外部クラス定義に存在する内部クラス定義から定義された名前は、内部クラス定義に拡張されません。
入れ子になったクラスを使用しない場合は、より良い場合があります。ネストする必要がある場合は、これを試してください:
x = 1
class OuterClass:
outer_var = x
class InnerClass:
inner_var = x
または、ネストする前に両方のクラスを宣言します。
class OuterClass:
outer_var = 1
class InnerClass:
inner_var = OuterClass.outer_var
OuterClass.InnerClass = InnerClass
(この後、必要であればdel InnerClass
できます。)
最も簡単なソリューション:
class OuterClass:
outer_var = 1
class InnerClass:
def __init__(self):
self.inner_var = OuterClass.outer_var
それはあなたが明示的であることを必要としますが、多くの努力をしません。
Pythonでは、可変オブジェクトが参照として渡されるため、外部クラスの参照を内部クラスに渡すことができます。
class OuterClass:
def __init__(self):
self.outer_var = 1
self.inner_class = OuterClass.InnerClass(self)
print('Inner variable in OuterClass = %d' % self.inner_class.inner_var)
class InnerClass:
def __init__(self, outer_class):
self.outer_class = outer_class
self.inner_var = 2
print('Outer variable in InnerClass = %d' % self.outer_class.outer_var)