ここで話しているのは、ネストされたクラスです。基本的に、モデリングしている2つのクラスがあります。 DownloadManagerクラスとDownloadThreadクラス。ここでの明らかなOOPコンセプトは合成です。ただし、合成は必ずしもネストを意味するわけではありませんか?
次のようなコードがあります。
class DownloadThread:
def foo(self):
pass
class DownloadManager():
def __init__(self):
dwld_threads = []
def create_new_thread():
dwld_threads.append(DownloadThread())
しかし今、私は入れ子が良い状況があるのだろうかと思っています。何かのようなもの:
class DownloadManager():
class DownloadThread:
def foo(self):
pass
def __init__(self):
dwld_threads = []
def create_new_thread():
dwld_threads.append(DownloadManager.DownloadThread())
これは、「内部」クラスが1回限りであり、外部クラスのdefinitionの外部では決して使用されない場合に行うことができます。たとえば、メタクラスを使用するには、行うのが便利な場合があります
class Foo(object):
class __metaclass__(type):
....
メタクラスを一度だけ使用する場合は、メタクラスを個別に定義する代わりに。
このようなネストされたクラスを使用したのは、それ以外の場合は、密接に関連するクラスのグループをグループ化するための名前空間としてのみ外部クラスを使用しました。
class Group(object):
class cls1(object):
...
class cls2(object):
...
次に、別のモジュールからGroupをインポートし、Group.cls1、Group.cls2などと呼ぶことができます。ただし、モジュールを使用することで、まったく同じ(おそらく混乱が少ない方法で)を達成できると主張するかもしれません。
私はPythonを知らないが、あなたの質問は非常に一般的だ。 Pythonに固有の場合は無視してください。
クラスのネストは、スコープに関するものです。あるクラスが別のクラスのコンテキストでのみ意味があると考える場合、前者はおそらくネストされたクラスになるのに適した候補です。
これは、ヘルパークラスをプライベートなネストされたクラスにする一般的なパターンです。
メタクラスを扱っている場合を除いて、これを行うメリットは実際にはありません。
クラス:スイートは本当にあなたが思っているものではありません。それは奇妙なスコープであり、奇妙なことをします。クラスを作ることすらありません!クラスの名前、ベース、属性の小さな辞書、メタクラスなど、いくつかの変数を収集する方法にすぎません。
名前、ディクショナリ、およびベースはすべて、メタクラスである関数に渡され、class:suiteがあったスコープ内の変数「name」に割り当てられます。
メタクラスをいじって、実際に標準のクラス内にクラスをネストすることで得られるものは、コードを読むのが難しく、コードを理解するのが難しく、なぜ「クラス」スコープは、他のpythonスコープとはまったく異なります。
クラスをクラスジェネレータとして使用している可能性があります。のように(いくつかのカフコードから:)
class gen(object):
class base_1(object): pass
...
class base_n(object): pass
def __init__(self, ...):
...
def mk_cls(self, ..., type):
'''makes a class based on the type passed in, the current state of
the class, and the other inputs to the method'''
この機能が必要になったとき、非常に明確になると思います。似たようなことをする必要がない場合は、おそらく良いユースケースではありません。
強化された機能が特定のネストされたクラスにカプセル化された継承されたクラスを構築する場合、ネストされたクラスには別の使用法があります。
この例を参照してください。
class foo:
class bar:
... # functionalities of a specific sub-feature of foo
def __init__(self):
self.a = self.bar()
...
... # other features of foo
class foo2(foo):
class bar(foo.bar):
... # enhanced functionalities for this specific feature
def __init__(self):
foo.__init__(self)
foo
のコンストラクターで、構築されるオブジェクトが実際にfoo
オブジェクトである場合、行self.a = self.bar()
はfoo.bar
を構築し、オブジェクトが構築される場合はfoo2.bar
オブジェクトを構築することに注意してください実際にはfoo2
オブジェクトです。
クラスbar
が代わりにクラスfoo
の外で定義され、その継承バージョン(たとえば、bar2
と呼ばれる)の場合、新しいクラスfoo2
を定義するのは非常に苦痛です。 foo2
のコンストラクターの最初の行をself.a = bar2()
に置き換える必要があるため、コンストラクター全体を書き換えることを意味します。
いいえ、構成はネストを意味しません。外側のクラスの名前空間でさらにクラスを非表示にする場合は、ネストされたクラスを使用するのが理にかなっています。
とにかく、私はあなたの場合のネストの実用的な使用を見ていません。コードが読みにくくなる(理解する)だけでなく、インデントが増えて行が短くなり、分割されやすくなります。