it-swarm-eu.dev

C'è un vantaggio nel definire una classe all'interno di un'altra classe in Python?

Quello di cui sto parlando qui sono le classi nidificate. In sostanza, ho due classi che sto modellando. Una classe DownloadManager e una classe DownloadThread. L'ovvio OOP qui è composizione. Tuttavia, composizione non significa necessariamente nidificazione, giusto?

Ho un codice simile a questo:

class DownloadThread:
    def foo(self):
        pass

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

Ma ora mi chiedo se c'è una situazione in cui la nidificazione sarebbe migliore. Qualcosa di simile a:

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

Potresti voler fare questo quando la classe "interna" è una tantum, che non verrà mai usata al di fuori della definizione della classe esterna. Ad esempio, per usare una metaclasse, a volte è utile farlo

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

invece di definire una metaclasse separatamente, se la usi solo una volta.

L'unica altra volta che ho usato classi nidificate in quel modo, ho usato la classe esterna solo come spazio dei nomi per raggruppare un gruppo di classi strettamente correlate:

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

    class cls2(object):
       ...

Quindi da un altro modulo, è possibile importare Group e fare riferimento a questi come Group.cls1, Group.cls2 ecc. Tuttavia si potrebbe sostenere che è possibile ottenere esattamente lo stesso risultato (forse in modo meno confuso) utilizzando un modulo.

108
dF.

Non conosco Python, ma la tua domanda sembra molto generale. Ignorami se è specifico di Python.

L'annidamento di classe riguarda tutto l'ambito. Se pensi che una classe abbia senso solo nel contesto di un'altra, allora la prima è probabilmente un buon candidato per diventare una classe nidificata.

È un modello comune rendere le classi helper come classi nidificate private.

18
André Chalella

Non c'è davvero alcun vantaggio nel fare questo, tranne se hai a che fare con i metaclassi.

la classe: suite non è proprio quello che pensi che sia. È uno scopo strano e fa cose strane. Non fa nemmeno una lezione! È solo un modo per raccogliere alcune variabili: il nome della classe, le basi, un piccolo dizionario di attributi e una metaclasse.

Il nome, il dizionario e le basi vengono tutti passati alla funzione che è la metaclasse, quindi viene assegnato alla variabile "nome" nell'ambito in cui si trovava la classe: suite.

Quello che puoi ottenere facendo confusione con le metaclasse e, in effetti, annidando le classi all'interno delle tue classi standard di borsa, è più difficile leggere il codice, più difficile da capire il codice e strani errori che sono terribilmente difficili da capire senza essere intimamente familiari con il motivo per cui la "classe" l'ambito è completamente diverso da qualsiasi altro ambito python.

6
Jerub

Potresti usare una classe come generatore di classi. Mi piace (in alcuni fuori il codice polsino :)

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

Sento che quando avrai bisogno di questa funzionalità ti sarà molto chiara. Se non hai bisogno di fare qualcosa di simile, probabilmente non è un buon caso d'uso.

5
tim.tadh

C'è un altro utilizzo per la classe nidificata, quando si vuole costruire classi ereditate le cui funzionalità avanzate sono incapsulate in una classe nidificata specifica.

Vedi questo esempio:

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)

Nota che nel costruttore di foo, la riga self.a = self.bar() costruirà un foo.bar Quando l'oggetto che viene costruito è in realtà un oggetto foo e un foo2.bar Oggetto quando l'oggetto in costruzione è in realtà un oggetto foo2.

Se invece la classe bar fosse definita al di fuori della classe foo, così come la sua versione ereditata (che ad esempio si chiamerebbe bar2), Allora definire la nuova classe foo2 Sarebbe molto più doloroso, perché il constatore di foo2 Dovrebbe avere la sua prima riga sostituita da self.a = bar2(), il che implica riscrivere l'intero costruttore.

4
Thomas

No, composizione non significa nidificazione. Avrebbe senso avere una classe nidificata se si desidera nasconderla di più nello spazio dei nomi della classe esterna.

Ad ogni modo, non vedo alcun uso pratico per nidificare nel tuo caso. Renderebbe il codice più difficile da leggere (capire) e aumenterebbe anche il rientro che renderebbe le linee più brevi e più inclini alla divisione.

1
Cristian Ciupitu