2009-07-12 2 views
7

Non credo, ma ho pensato di chiederlo per ogni evenienza. Ad esempio, per l'uso in una classe che incapsula un int:python ha operatori di conversione?

i = IntContainer(3) 
i + 5 

E non sono solo interessati a questo int esempio, ero alla ricerca di qualcosa di pulito e generale, non ignorando ogni int e metodo di stringa.

Grazie, sunqiang. È proprio quello che volevo. Non mi ero reso conto che potevi sottoclassi questi tipi immutabili (provenienti dal C++).

class IntContainer(int): 
    def __init__(self,i): 
     #do stuff here 
     self.f = 4 

    def MultiplyBy4(self): 
     #some member function 
     self *= self.f 
     return self 

print 3+IntContainer(3).MultiplyBy4() 

risposta

3

a volte forse solo sottoclasse da int è sufficiente. quindi __add__ e __radd__ non è necessario il costume.

class IntContainer(int): 
    pass 
i = IntContainer(3) 
print i + 5 # 8 
print 4 + i # 7 

class StrContainer(str): 
    pass 
s = StrContainer(3) 
print s + '5' # 35 
print '4' + s # 43 
3

È questo quello che ti serve?

In [1]: class IntContainer(object): 
    ...:  def __init__(self, val): 
    ...:   self.val = val 
    ...:  def __add__(self, val): 
    ...:   return self.val + val 
    ...:  def __radd__(self, val): 
    ...:   return self.val + val 
    ...: 
    ...: 

In [2]: i = IntContainer(3) 

In [3]: i + 5 
Out[3]: 8 

In [4]: 
+1

Non proprio. Stavo cercando qualcosa come l'operatore di conversione C++, che sostituisce intelligentemente l'oggetto contenitore con qualunque cosa contenga nelle espressioni. – Alex

+0

Questo fallirà per "5 + i", credo. – ars

+0

ars, hai ragione, ho visto la tua risposta e mi manca __radd__ ... immagino che ora sia ok dopo aver cambiato la mia risposta ... –

11

Questo dovrebbe fare quello che ti serve:

class IntContainer(object): 
    def __init__(self, x): 
     self.x = x 

    def __add__(self, other): 
     # do some type checking on other 
     return self.x + other 

    def __radd__(self, other): 
     # do some type checking on other 
     return self.x + other 

uscita:

In [6]: IntContainer(3) + 6 
Out[6]: 9 

In [7]: 6 + IntContainer(3) 
Out[7]: 9 

Per ulteriori informazioni cercare "Radd" nei seguenti documenti:

Troverete altri tali metodi per "Oltre a destra", "sottrazione giusto", ecc

Ecco un altro link che copre gli stessi operatori:

A proposito, Python ha operatori di casting:

Ma, essi non compiere ciò che è necessario nel tuo esempio (fondamentalmente perché i metodi non hanno alcun tipo di annotazione per i parametri, quindi non c'è buon modo per lanciare in modo implicito). Così si può fare questo:

class IntContainer2(object): 
    def __init__(self, x): 
     self.x = x 

    def __int__(self): 
     return self.x 


ic = IntContainer2(3) 
print int(ic) + 6 
print 6 + int(ic) 

Ma questa avrà esito negativo:

print ic + 6 # error: no implicit coercion 
3

Non si ottiene operatori di conversione come in C++ perché Python non ha questo tipo di forte sistema di tipo statico. Gli unici operatori di conversione automatici sono quelli che gestiscono i valori numerici predefiniti (int/float); sono predefiniti nella lingua e non possono essere modificati.

Il tipo "conversione" viene solitamente eseguito da costruttori/fabbriche. È quindi possibile sovraccaricare metodi standard come __add__ per farlo funzionare più come altre classi.

0

Ci scusiamo per essere venuti alla festa con 8.5 anni di ritardo. È possibile derivare da un valore immutabile (cioè int). Non è possibile definire __init__ poiché l'immutabile è già stato creato e non può essere modificato (per definizione). Questo è dove __new__ è utile.

class IntContainer(int): 
    def __new__ (cls, val): 
     ival = int.__new__(cls, val) 
     ival._rval = 'IntContainer(%d)' % ival 
     return ival 
    def __repr__ (self): 
     return self._rval 

In [1]: i = IntContainer(3) 

In [2]: i 
Out[2]: IntContainer(3) 

In [3]: repr(i) 
Out[3]: 'IntContainer(3)' 

In [4]: str(i) 
Out[4]: '3' 

In [5]: i + 5 
Out[5]: 8 

In [6]: 4 + i 
Out[6]: 7 

In [7]: int(i) 
Out[7]: 3 

In [8]: float(i) 
Out[8]: 3.0 

Ora, per rispondere alla tua domanda su operatori di conversione. È inoltre possibile definire __int__, __long__, __float__ e, ovviamente, __str__. Per convertire o eseguire il cast su un oggetto arbitrario, sarà probabilmente necessario modificare l'altro oggetto per ottenere ciò che desideri. È possibile utilizzare il metodo __new__ di quell'altro oggetto. O se l'altro oggetto è già stato creato, prova a utilizzare __call__.