2016-03-11 64 views
6

In Python 3.4, vorrei creare una sottoclasse di float - qualcosa che può essere utilizzato in operazioni matematiche e booleane come un float, ma ha altre funzionalità personalizzate e può ricevere un argomento all'inizializzazione che controlla tale funzionalità. (In particolare, volevo avere un parametro personalizzato __str__ e un parametro utilizzato in questo metodo.)Python: una sottoclasse di float può prendere argomenti extra nel suo costruttore?

Tuttavia, non riesco a ottenere una sottoclasse di float per avere un costruttore funzionale a due argomenti. Perché? Si tratta semplicemente di una limitazione all'estensione dei tipi built-in?

Esempio:

class Foo(float): 
    def __init__(self, value, extra): 
     super().__init__(value) 
     self.extra = extra 

Ora, se provo Foo(1,2) ottengo:

TypeError: float() takes at most 1 argument (2 given) 

Sorprendentemente, vengono applicate anche argomenti miei nuovi __init__ 's, quindi se lo faccio Foo(1) ottengo:

TypeError: __init__() missing 1 required positional argument: 'extra' 

Qual è l'affare qui? Ho fatto cose simili con i sottotipi di list e sono rimasto sorpreso che non funzionasse su float.

+3

correlati: http://stackoverflow.com/questions/1936457/sub-classing-float-type-in- python-fail-to-catch-exception-in-init –

+2

Non una risposta alla tua domanda, ma una soluzione al tuo problema: http://ideone.com/nIPim9 –

+0

Interessante, @ Robᵩ. Sembra che l'override di '__new__' potrebbe essere il modo di fare ciò che voglio, ma non esattamente sicuro su come farlo funzionare ancora. –

risposta

7

Poiché float è immutabile, è necessario sovrascrivere anche __new__. Il seguente dovrebbe fare quello che vuoi:

class Foo(float): 
    def __new__(self, value, extra): 
     return float.__new__(self, value) 
    def __init__(self, value, extra): 
     float.__init__(value) 
     self.extra = extra 

foo = Foo(1,2) 
print(str(foo)) 
1.0 
print(str(foo.extra)) 
2 

Vedi anche Sub-classing float type in Python, fails to catch exception in __init__()

+0

Sì, questo è un approccio di lavoro - grazie! Sono ancora perplesso dal motivo per cui è necessario, però. Per il tuo metodo '__init__',' self' è un 'float' non un' Foo', giusto? Perché l'abbiamo creato tramite 'float .__ new__'? –

+0

In realtà, http://stackoverflow.com/a/13534717/204131 fa notare che 'float .__ new__' è passato un parametro di' Foo', quindi dovrebbe creare un'istanza di 'Foo' piuttosto che di float. –

3

la soluzione di cgogolin è giusto. è in questo modo con un altro classi immutabili come int, str ... Ma io scriverò:

class Foo(float): 
    def __new__(cls, value, extra): 
     return super().__new__(cls, value) 
    def __init__(self, value, extra): 
     float.__init__(value) 
     self.extra = extra 
+0

dov'è cgogolin? –

+0

la sua risposta è sopra – qvpham