2008-08-28 25 views
10

estoy tratando de extender algunas clases de "base" en Python:Ampliación de clases 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) 

Funciona bien en el caso lista porque el anexar método modifica el objeto "en su sitio ", sin devolverlo. Pero en el caso int, el método agregar no modifica el valor de la variable externa x. Supongo que está bien en el sentido de que auto es una variable local en el añadir método de la clase, pero esto me está impidiendo la modificación del valor inicial asignado a la instancia de la clase.

¿Es posible extender una clase de esta manera o debería definir una propiedad de clase con el tipo de base y mapear todos los métodos necesarios para esta propiedad?

Respuesta

5

int es un tipo de valor, por lo que cada vez que haga una asignación, (por ejemplo, las dos instancias de + = arriba), no modifica el objeto que tiene en el montón, pero reemplaza la referencia con uno de los resultados del lado derecho de la asignación (es decir, una int)

lista no es un tipo de valor, por lo que no está sujeto a las mismas reglas.

esta página tiene más detalles sobre las diferencias: http://docs.python.org/ref/objects.html

OMI, sí, usted debe definir una nueva clase que mantiene un int como una instancia de variable

+4

Python no tiene "tipos de valores" ni tipos de referencia. La distinción entre tipos mutables e inmutables es solo algo similar y no se basa en ese tipo de distinción. Sin embargo, su recomendación de usar composición en lugar de herencia es excelente. –

0

Entrs son inmutables y no se puede modificar en su lugar, por lo que hay que ir con la opción # 2 (porque la opción # 1 es imposible sin algún truco).

23

Sus dos xint ejemplos no funcionan para dos diferentes razones.

El primero no funciona porque self += value es equivalente a self = self + value que acaba reasigna la variable local self a un objeto diferente (un número entero), pero no cambia el objeto original. Realmente no se puede conseguir este

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

trabajar con una subclase de int ya que son números enteros immutable.

Para obtener el segundo para trabajar se puede definir un __add__ method, así:

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

amplié que Listax clase sólo un poco, hizo lo que pudo encontrar todos los puntos de índice de un número por lo que es para que pueda extender con múltiples listas a la vez, lo inicialice y lo haga para que pueda recorrerlo

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)