2008-08-28 10 views
10

Je suis en train d'étendre quelques « base » des classes en Python:extension des classes de base en Python

class xlist (list): 
    def len(self): 
     return len(self) 

    def add(self, *args): 
     self.extend(args) 
     return None 


class xint (int): 
    def add(self, value): 
     self += value 
     return self 


x = xlist([1,2,3]) 
print x.len() ## >>> 3 ok 
print x   ## >>> [1,2,3] ok 
x.add (4, 5, 6) 
print x   ## >>> [1,2,3,4,5,6] ok 

x = xint(10) 
print x   ## >>> 10 ok 
x.add (2) 
print x   ## >>> 10 # Not ok (#1) 

print type(x)   ## >>> <class '__main__.xint'> ok 
x += 5 
print type(x)   ## >>> <type 'int'> # Not ok (#2) 

Il fonctionne très bien dans la liste cas parce que le append méthode modifie l'objet « en place ", sans le retourner. Mais dans le cas int, la méthode ajouter ne modifie pas la valeur de la variable externe x. Je suppose que c'est bien dans le sens que self est une variable locale dans la méthode add de la classe, mais cela m'empêche de modifier la valeur initiale affectée à l'instance de la classe.

Est-il possible d'étendre une classe de cette façon ou dois-je définir une propriété de classe avec le type de base et mapper toutes les méthodes nécessaires à cette propriété?

Répondre

5

int est un type de valeur, de sorte que chaque fois que vous faites une cession, (par exemple, les deux instances de + = ci-dessus), il ne modifie pas l'objet que vous avez sur le tas, mais remplace la référence avec l'un des résultats du côté droit de l'affectation (c'est-à-dire un int)

La liste n'est pas un type de valeur, elle n'est donc pas liée par les mêmes règles.

cette page a plus de détails sur les différences: http://docs.python.org/ref/objects.html

OMI, oui, vous devez définir une nouvelle classe qui garde un int comme une variable d'instance

+4

Python n'a pas de "types de valeur" et de types de référence. La distinction entre les types mutables et immuables est seulement quelque peu similaire et ne repose pas sur ce genre de distinction. Votre recommandation d'utiliser la composition au lieu de l'héritage est grande, cependant. –

0

Les Ints sont immuables et vous ne pouvez pas les modifier sur place, donc vous devriez aller avec l'option # 2 (parce que l'option # 1 est impossible sans une supercherie).

23

Vos deux xint exemples ne fonctionnent pas pour deux des raisons différentes.

Le premier ne fonctionne pas parce que self += value est équivalent à self = self + value qui réaffecte juste la variable locale self à un autre objet (un entier), mais ne change pas l'objet original. Vous ne pouvez pas vraiment obtenir ce

>>> x = xint(10) 
>>> x.add(2) 

de travailler avec une sous-classe de int depuis entiers sont immutable.

Pour obtenir le second au travail, vous pouvez définir un __add__ method, comme ceci:

class xint(int): 
    def __add__(self, value): 
     return xint(int.__add__(self, value)) 

>>> x = xint(10) 
>>> type(x) 
<class '__main__.xint'> 
>>> x += 3 
>>> x 
13 
>>> type(x) 
<class '__main__.xint'> 
2

i vous avez décompressé XLIST classe juste un peu, fait vous pouvez donc trouver tous les points d'index d'un certain nombre rendant donc vous pouvez étendre avec plusieurs listes à la fois en le faisant initialiser et en le faisant ainsi vous pouvez parcourir it iter

class xlist: 
    def __init__(self,alist): 
     if type(alist)==type(' '): 
      self.alist = [int(i) for i in alist.split(' ')] 
     else: 
      self.alist = alist 
    def __iter__(self): 
     i = 0 
     while i<len(self.alist): 
      yield self.alist[i] 
      i+=1 
    def len(self): 
     return len(self.alist) 
    def add(self, *args): 
     if type(args[0])==type([1]): 
      if len(args)>1: 
       tmp = [] 
       [tmp.extend(i) for i in args] 
       args = tmp 
      else:args = args[0] 
     if type(args)==type(''):args = [int(i) for i in args.split(' ')] 
     (self.alist).extend(args) 
     return None 
    def index(self,val): 
     gen = (i for i,x in enumerate(self.alist) if x == val) 
     return list(gen) 
Questions connexes