2012-04-08 5 views
70

Esiste qualche regola su quali classi di libreria incorporate e standard non siano sottoclasse ("finale")?Quali classi non possono essere sottoclasse?

Come di Python 3.3, ecco alcuni esempi:

  • bool
  • function
  • operator.itemgetter
  • slice

Ho trovato un question che si occupa della realizzazione di classi "finali", entrambe in C e puro Python.

Mi piacerebbe capire quali ragioni possono spiegare perché una classe viene scelta come "definitiva" in primo luogo.

+4

'NoneType' è un altro esempio. – Duncan

+4

Una classe finale in una implementazione Python può essere sottoclasmabile in un'altra implementazione? Spero che qualcuno possa confermare che non succede mai. Altrimenti, il codice scritto per un'implementazione potrebbe interrompersi quando trasferito su un'altra (anche molto dolorosamente: immagina se qualcuno ha sottoclasse 'function', e ora ha bisogno di rifattorizzare il codice per evitare questa ereditarietà). – max

+3

Nota che PyPy si rifiuta di sottoclasse anche i tuoi quattro esempi ... anche se non ha la restrizione CPython. Potrebbero avere una ragione documentata nella loro base di codice. –

risposta

23

Sembra che ci siano due motivi per cui una classe è "finale" in Python.

1. La violazione di invariante di classe

Le classi che seguono pattern Singleton hanno un invariante che c'è un numero limitato (predeterminato) di istanze. Qualsiasi violazione di questa invariante in una sottoclasse sarà incoerente con l'intento della classe e non funzionerebbe correttamente. Esempi:

  • bool: True, False; vedi Guido's comments
  • NoneType: None
  • NotImplementedType: NotImplemented
  • ellipsis: Ellipsis

Ci possono essere casi diversi dal pattern Singleton in questa categoria, ma io non sono a conoscenza di alcuna.

2. No Persuasive Use Case

Una classe implementato in C richiede un lavoro supplementare per consentire la creazione di sottoclassi (almeno in CPython). Fare questo lavoro senza un caso di utilizzo convincente non è molto allettante, quindi i volontari hanno meno probabilità di farsi avanti. Esempi:

Nota 1:

Ho inizialmente pensato che ci fossero casi d'uso valide, ma l'interesse semplicemente insufficiente, in sottoclassi di function e operator.itemgetter. Grazie a @agf per aver sottolineato che i casi d'uso offerti here e here non sono convincenti (vedi i commenti @agf alla domanda).

Nota 2:

mia preoccupazione è che un'altra implementazione di Python potrebbe accidentalmente consentire sottoclasse una classe che è in definitiva CPython. Ciò può causare codice non portatile (un caso d'uso può essere debole, ma qualcuno potrebbe scrivere codice che sottoclasse function se il loro Python lo supporta). Questo può essere risolto contrassegnando nella documentazione di Python tutte le classi di libreria standard e incorporate che non possono essere sottoclasse e richiedendo che tutte le implementazioni seguano il comportamento di CPython a tale riguardo.

Nota 3:

Il messaggio prodotto da CPython in tutti i casi di cui sopra è:

TypeError: type 'bool' is not an acceptable base type 

E 'abbastanza criptico, come numerose domande in questo show soggetto. Presenterò un suggerimento per aggiungere un paragrafo alla documentazione che spiega le classi finali e forse anche il messaggio di errore:

TypeError: type 'bool' is final (non-extensible) 
+3

Ovviamente se stavi scrivendo una simulazione di Schrodinger's Cat, potresti voler sottoclasse 'bool' per includere' unknown' :-P sto scherzando – Endophage

+8

@Endophage: un Qbit sarebbe sicuramente un tipo utile, ma non è un sottolivello di 'bool', infatti, al contrario, ogni singolo valore booleano è un tipo di qbit! uno che capita di essere osservato. Probabilmente gestirò il caso con '__subclasscheck__' e gli amici, comunque. – SingleNegationElimination

+4

@TokenMacGuy osservazione eccellente! Quindi, perché non abbiamo una classe Qbit in Python che bool è una sottoclasse di! Io chiedo che dovrebbe essere così! :-P – Endophage