2014-11-04 12 views
5

A parte l'ovvio, ho pensato di provare questo, nel caso in cui:C'è un modo per creare una sottoclasse di un generatore in Python 3?

def somegen(input=None): 
    ... 
    yield 
    ... 

gentype = type(somegen()) 
class subgen(gentype): 
    def best_function_ever(): 
     ... 

Ahimè, la risposta di Python era abbastanza ostile:

"TypeError: Type generator is not an acceptable base type" 

Per fortuna ha voluto che, questo è un problema per me. Vedi, stavo pensando che forse sarebbe essere un tipo di base divertente con cui giocare, se avessi dato una possibilità. Immagina la mia sorpresa! ..e sgomento. Non c'è modo di convincere l'onnipotente Python a vedere le cose a modo mio su questo?

Questa è sicuramente una domanda tipo "fuori dalla scatola", quindi per favore non dire che non è possibile se non si riesce a pensare a un modo immediatamente. Python (specialmente Py3) è molto flessibile.

Naturalmente, se avete la prova del motivo per cui non può (non "non dovrebbe") essere un tipo di base (PY3), poi ho fare vogliono vedere e capire che.

+0

Un 'generatore' è un tipo di' metodo'. Una 'classe' può ereditare solo da altre' classi'. Sarebbe analogo costruire un'automobile senza guida. Posso capire la frustrazione perché sono dell'opinione che python dovrebbe essere in grado di fare qualsiasi cosa e tutto, ma capisco perché non si prenderanno il tempo per implementarlo. –

+0

@FarmerJoe Non sono sicuro di ottenere l'analogia, ma un 'metodo' è essenzialmente (forse anche in realtà) un sottotipo di' funzione'. Inoltre, tutto è un tipo, anche il tipo stesso) – Inversus

+0

@FarmerJoe Ciò che intendo è che, sotto le copertine, tutto è un 'class', anche' generatore'. Da qualche parte nelle profondità interne, si troverà sicuramente qualche equivalente C di 'generatore di classi (funzione)' ed è quella classe che sto cercando di "sottoclasse" (cioè: sono perfettamente felice di fare qualcos'altro che mi consenta una simile flessibilità) . – Inversus

risposta

1

Non è possibile creare una sottoclasse di un generatore definito come funzione utilizzando yield, ma è possibile utilizzarlo in un altro generatore.

Basta prendere questa semplice:

def alphagen(n=27): 
    if n<0 or n > 27: n = 27 
    for i in range(n): 
     yield chr(ord('A') + i) 

Si ottiene:

>>>> [ a for a in alphagen(10)] 
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'] 

si può utilizzare in:

def alphastartgen(n=27): 
    resul = "" 
    for i in alphagen(n): 
     resul += i 
     yield resul 

E ora si ottiene:

>>> [ a for a in alphastartgen(8) ] 
['A', 'AB', 'ABC', 'ABCD', 'ABCDE', 'ABCDEF', 'ABCDEFG', 'ABCDEFGH'] 
+0

È un angolo affascinante .. Vado a giocare con lui per un po '. Tornerò. Grazie – Inversus

+0

Sono tornato dal giocare un po ', e devo dire: "Oh ya. Questa è la roba buona". Trattare la definizione del generatore esterno (funzione) come una definizione di classe è esattamente il tipo di matto che speravo. Grazie mille. – Inversus

2

Un'altra domanda pertinente è Which classes cannot be subclassed?.

È la ragione 2 nella risposta accettata - la sottoclasse di un tipo deve essere implementata in C, e non è stata implementata per i generatori, probabilmente perché nessuno ha visto un caso d'uso.

Il codice sorgente per gli oggetti del generatore è genobject.c e sulla riga 349 è possibile vedere che il flag Py_TPFLAGS_BASETYPE non è impostato.

+1

Ooo. Bello. È questa l'unica cosa che mi impedisce di sottoclassi un gen? Ci sono altre parti degli interni che dovrebbero essere convinte? Questo può essere fatto in fase di runtime (monkeypatch?) O potrei aver bisogno di creare una build personalizzata? (una lunga strada che sto cercando di evitare per il momento lol) – Inversus

+0

Inoltre .. come hai trovato quella bandiera?Come, tu lo sapevi, o hai seguito il codice lì o qualcosa del genere? – Inversus

+0

I cercato su Google e ho trovato il thread Stack Overflow precedente a cui mi sono collegato, e lo ho letto ... E la flag non è sufficiente, devi anche _implementare come funzionerebbe (vedi, diciamo, il codice per la lista), e ricompilare Python. – RemcoGerlich

Problemi correlati