2009-07-12 4 views
7

Je ne pense pas, mais je pensais que je demanderais juste au cas où. Par exemple, pour une utilisation dans une classe qui encapsule un int:python a-t-il des opérateurs de conversion?

i = IntContainer(3) 
i + 5 

Et je ne suis pas seulement intéressé par cet exemple int, je cherchais quelque chose de propre et général, pas remplaçant tous les int et méthode de chaîne.

Merci, sunqiang. C'est juste ce que je voulais. Je n'avais pas réalisé que vous pouviez sous-classer ces types immuables (venant de 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() 

Répondre

3

parfois peut-être juste une sous-classe de int directement est suffisant. alors __add__ et __radd__ n'ont pas besoin de coûter.

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

Est-ce ce que vous cherchez?

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

Pas vraiment. Je cherchais quelque chose comme l'opérateur de conversion C++, qui remplace intelligemment l'objet conteneur par ce qu'il contient dans les expressions. – Alex

+0

Cela échouera pour "5 + i", je crois. – ars

+0

ars, vous avez raison, j'ai vu votre réponse et il me manque __radd__ ... Je suppose que maintenant c'est ok après avoir changé ma réponse ... –

11

Cela devrait faire ce que vous avez besoin:

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 

Sortie:

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

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

Pour plus de recherche d'information pour "Radd" dans les documents suivants:

Vous trouverez d'autres procédés pour "plus droit", "soustraction droite", etc.

Voici un autre lien couvrant les mêmes opérateurs:

En passant, Python a des opérateurs de casting:

Mais, ils ne seront pas accomplir ce que vous avez besoin dans votre exemple (essentiellement parce que les méthodes n'ont pas annotation de type pour les paramètres, donc il n'y a pas de bonne façon de lancer implicitement). Ainsi, vous pouvez faire ceci:

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) 

Mais cela ne fonctionne pas:

print ic + 6 # error: no implicit coercion 
3

Vous n'obtiendrez les opérateurs de conversion comme en C++ parce que Python n'a pas ce genre de système solide de type statique. Les seuls opérateurs de conversion automatique sont ceux qui gèrent les valeurs numériques par défaut (int/float); ils sont prédéfinis dans la langue et ne peuvent pas être modifiés.

Le type "conversion" est généralement effectué par des constructeurs/usines. Vous pouvez alors surcharger les méthodes standard comme __add__ pour le faire fonctionner plus comme les autres classes.

0

Désolé de venir à la fête avec 8,5 ans de retard. Vous pouvez dériver d'un immutable (c'est-à-dire int). Vous ne pouvez pas définir __init__ car l'immutable est déjà créé et ne peut pas être modifié (par définition). C'est là que __new__ est très pratique.

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 

Maintenant, pour répondre à votre question sur les opérateurs de conversion. Vous pouvez également définir __int__, __long__, __float__ et, évidemment, __str__. Pour convertir ou convertir un objet arbitraire, vous devrez probablement modifier l'autre objet pour obtenir ce que vous voulez. Vous pouvez utiliser la méthode __new__ de cet autre objet. Ou si l'autre objet est déjà créé, essayez d'utiliser __call__.

Questions connexes