Frage Hat es einen Vorteil, eine Klasse in einer anderen Klasse in Python zu definieren?


Worüber ich hier spreche, sind verschachtelte Klassen. Im Wesentlichen habe ich zwei Klassen, die ich modelliere. Eine DownloadManager-Klasse und eine DownloadThread-Klasse. Das offenkundige OOP-Konzept ist hier die Komposition. Komposition bedeutet aber nicht unbedingt Nesting, oder?

Ich habe einen Code, der ungefähr so ​​aussieht:

class DownloadThread:
    def foo(self):
        pass

class DownloadManager():
    def __init__(self):
        dwld_threads = []
    def create_new_thread():
        dwld_threads.append(DownloadThread())

Aber jetzt frage ich mich, ob es eine Situation gibt, in der das Nisten besser wäre. Etwas wie:

class DownloadManager():
    class DownloadThread:
        def foo(self):
            pass
    def __init__(self):
        dwld_threads = []
    def create_new_thread():
        dwld_threads.append(DownloadManager.DownloadThread())

76
2017-09-17 01:12


Ursprung


Antworten:


Sie können dies tun, wenn die "innere" Klasse eine einmalige ist, die nie außerhalb der verwendet wird Definition der äußeren Klasse. Zum Beispiel, um eine Metaklasse zu verwenden, ist es manchmal praktisch, dies zu tun

class Foo(object):
    class __metaclass__(type):
        .... 

anstatt eine Metaklasse separat zu definieren, wenn Sie sie nur einmal verwenden.

Das einzige andere Mal, als ich verschachtelte Klassen wie diese verwendet habe, habe ich die äußere Klasse nur als Namespace benutzt, um eine Menge eng verwandter Klassen zu gruppieren:

class Group(object):
    class cls1(object):
       ...

    class cls2(object):
       ...

Dann können Sie aus einem anderen Modul eine Gruppe importieren und auf diese als Group.cls1, Group.cls2 usw. verweisen. Man könnte jedoch argumentieren, dass Sie dasselbe (vielleicht auf eine weniger verwirrende Weise) mit einem Modul erreichen können.


99
2017-09-17 01:14



Ich kenne Python nicht, aber deine Frage scheint sehr allgemein zu sein. Ignoriere mich, wenn es spezifisch für Python ist.

Bei der Klassenverschachtelung dreht sich alles um den Umfang. Wenn Sie denken, dass eine Klasse nur im Zusammenhang mit einer anderen sinnvoll ist, dann ist die erste wahrscheinlich ein guter Kandidat, um eine verschachtelte Klasse zu werden.

Es ist ein allgemeines Muster, Hilfsklassen als private, verschachtelte Klassen zu machen.


18
2017-09-17 01:52



Es ist wirklich kein Vorteil, dies zu tun, außer wenn Sie mit Metaklassen zu tun haben.

Die Klasse: Suite ist wirklich nicht das, was Sie denken, dass es ist. Es ist ein seltsamer Bereich, und es macht seltsame Dinge. Es macht wirklich nicht einmal eine Klasse! Es ist nur eine Möglichkeit, einige Variablen zu sammeln - den Namen der Klasse, die Basen, ein kleines Verzeichnis von Attributen und eine Metaklasse.

Der Name, das Wörterbuch und die Basen werden alle an die Funktion übergeben, die die Metaklasse ist, und dann wird sie der Variablen 'name' in dem Bereich zugewiesen, in dem sich die Klasse: suite befand.

Was Sie durch das Mischen mit Metaklassen und durch das Verschachteln von Klassen innerhalb Ihrer Standardklassen erreichen können, ist schwerer Code zu lesen, schwerer zu verstehender Code und seltsame Fehler, die schwer zu verstehen sind, ohne genau zu wissen, warum die 'Klasse' scope unterscheidet sich grundlegend von allen anderen Python-Scopes.


5
2017-09-17 01:34



Sie könnten eine Klasse als Klassengenerator verwenden. Wie (in irgendeinem Code aus dem Ärmel :)

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'''

Ich habe das Gefühl, wenn Sie diese Funktionalität benötigen, wird es Ihnen sehr klar sein. Wenn Sie nicht etwas ähnliches tun müssen, ist es wahrscheinlich kein guter Anwendungsfall.


4
2017-09-17 01:11



Nein, Zusammensetzung bedeutet nicht Nesting. Es wäre sinnvoll, eine verschachtelte Klasse zu haben, wenn Sie sie mehr im Namespace der äußeren Klasse verstecken wollen.

Wie auch immer, ich sehe keinen praktischen Nutzen für das Nisten in deinem Fall. Es würde den Code schwerer lesbar machen (verstehen) und es würde auch die Einrückung vergrößern, was die Zeilen kürzer und anfälliger für Aufspaltungen machen würde.


1



Es gibt eine weitere Verwendung für geschachtelte Klassen, wenn man geerbte Klassen konstruieren möchte, deren erweiterte Funktionalitäten in einer bestimmten geschachtelten Klasse gekapselt sind.

Siehe dieses Beispiel:

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)

Beachten Sie, dass im Konstruktor von foo, die Linie self.a = self.bar() wird ein bauen foo.bar wenn das zu konstruierende Objekt tatsächlich ein ist foo Objekt und a foo2.bar Objekt, wenn das zu konstruierende Objekt tatsächlich ein foo2 Objekt.

Wenn die Klasse bar wurde außerhalb der Klasse definiert foo stattdessen, sowie seine geerbte Version (die würde heißen bar2 zum Beispiel), und dann die neue Klasse definieren foo2 wäre viel schmerzhafter, weil der Konstrukteur von foo2 müsste seine erste Zeile durch ersetzt haben self.a = bar2(), was bedeutet, dass der gesamte Konstruktor neu geschrieben wird.


0