2010-10-15 5 views
17

Recentemente stavo passando per un problema di codifica che stavo avendo e qualcuno guardando il codice ha detto che la lista delle sottoclassi era cattiva (il mio problema non era correlato a quella classe). Ha detto che non dovresti farlo e che è venuto con un sacco di effetti collaterali negativi. È vero?Cosa prendere in considerazione prima della lista delle sottoclassi?

Sto chiedendo se la lista è in genere cattiva sottoclasse e se sì, quali sono le ragioni. In alternativa, cosa devo considerare prima della lista delle sottoclassi in Python?

+2

L'elenco delle sottoclassi non è intrinsecamente negativo, ma ci sono molti casi in cui non è proprio ciò che si vuole fare. Non possiamo rispondere se questo è il caso qui, a meno che tu non ci dia specifiche. –

risposta

17

Non ci sono vantaggi nella sottoclasse list. Nessuno dei metodi utilizzerà metodi sovrascritti, pertanto è possibile che si verifichino errori imprevisti. Inoltre, è molto spesso confuso fare cose come self.append anziché self.foos.append o in particolare self[4] anziché self.foos[4] per accedere ai tuoi dati. È possibile creare qualcosa che funziona esattamente come un elenco o (migliore) come una lista che si desidera veramente durante la sottoclasse object.

+3

Cosa fare se si desidera aggiungere un attributo a un elenco? Ad esempio, supponiamo di avere mylist = []. Vogliamo qualcosa come mylist.x = 3. – riza

+1

@ Selinap, Nel caso in cui volessi che il mio stato includesse un elenco di qualcosa e un int, probabilmente utilizzerei ancora la composizione. Usare l'ereditarietà per questo apre confusione nella scrittura, confusione nell'uso e non ti guadagna nulla. –

+2

Questo sembra non essere vero per Python 3. Questi contengono ['collections.UserList'] (https://docs.python.org/3.4/library/collections.html#collections.UserList) esplicitamente per questo scopo. Suggerisce anche che la sottoclasse dalla lista sia ora possibile: "La necessità di questa classe è stata parzialmente soppiantata dalla possibilità di sottoclasse direttamente dalla lista;" (Capisco che questo è un vecchio argomento e probabilmente i commenti sopra erano veri mentre erano scritti, voglio solo chiarire per le persone che trovano questa domanda ora) – Claude

11

Penso che la prima domanda che mi pongo è: "Il mio nuovo oggetto è davvero una lista?". Cammina come una lista, parla come una lista? O è qualcos'altro?

Se si tratta di un elenco, tutti i metodi di elenco standard dovrebbero avere senso.

Se i metodi dell'elenco standard non hanno senso, l'oggetto dovrebbe contenere un elenco, non un elenco.

Nella vecchia lista di sottoclasse di python (2.2?) Era una cattiva idea per vari motivi tecnici, ma in un python moderno va bene.

+4

+1 eredita solo quando realmente ha senso al 100%, altrimenti componi. – delnan

+0

Per quanto riguarda gli effetti collaterali, era un po 'fuori moda? I dati sono contenuti in una lista, ma ci sono molti altri metodi specifici che ho bisogno di buttare in cima per fare una serie di cose. –

+0

sì, eredita le relazioni "is-a", componga praticamente tutto il resto. –

6

Nick è corretto. Inoltre, mentre non posso parlare con Python, in altri linguaggi OO (Java, Smalltalk) la sottoclasse di una lista è una cattiva idea. L'ereditarietà in generale dovrebbe essere evitata e viene utilizzata la composizione delle deleghe.

Piuttosto, si effettua una classe contenitore e si delegano le chiamate all'elenco. La classe contenitore ha un riferimento all'elenco e puoi persino esporre le chiamate e i ritorni dell'elenco con i tuoi metodi. Questo aggiunge flessibilità e consente di modificare l'implementazione (un diverso tipo di elenco o struttura dati) in seguito senza rompere alcun codice. Se vuoi che il tuo elenco faccia cose di tipo listy differenti, il tuo contenitore può farlo e usa l'elenco semplice come una semplice struttura di dati. Immagina se avessi 47 diversi usi delle liste. Vuoi davvero mantenere 47 sottoclassi diverse? Invece si potrebbe fare questo tramite il contenitore e le interfacce. Una classe per mantenere e consentire alle persone di chiamare i tuoi metodi nuovi e migliorati tramite l'interfaccia (o le interfacce) con l'implementazione rimanente nascosta.

17

abstract base classes fornito nel modulo collections, in particolare MutableSequence, può essere utile quando si implementano classi di tipo elenco. Questi sono disponibili in Python 2.6 e versioni successive.

Con ABC è possibile implementare la funzionalità "core" della classe e fornirà i metodi che dipendono logicamente da ciò che è stato definito.

Per esempio, l'implementazione __getitem__ in una classe -derived collections.Sequence sarà sufficiente per fornire la classe con __contains__, __iter__, e altri metodi.

È possibile continuare a utilizzare un oggetto elenco contenuto per eseguire il sollevamento pesante.

+1

Dal momento che Python 3.3+ è stato spostato nel modulo ['collections.abc'] (https://docs.python.org/3/library/collections.abc.html). – xmedeko