name - python telegram bot
Extender clases base en Python (4)
Los Ints son inmutables y no puedes modificarlos en su lugar, por lo que debes ir con la opción n. ° 2 (porque la opción n. ° 1 es imposible sin algunos trucos).
Estoy tratando de extender algunas 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 de la lista porque el método de agregar modifica el objeto "en su lugar", sin devolverlo. Pero en el caso int , el método add no modifica el valor de la variable x externa. Supongo que está bien en el sentido de que self es una variable local en el método add de la clase, pero esto me impide modificar el valor inicial asignado a la instancia de la clase.
¿Es posible extender una clase de esta manera o debo definir una propiedad de clase con el tipo base y asignar todos los métodos necesarios a esta propiedad?
int es un tipo de valor, por lo que cada vez que haces una asignación (por ejemplo, ambas instancias de + = arriba), no modifica el objeto que tienes en el montón, sino que reemplaza la referencia con uno del resultado de la mano derecha lado de la tarea (es decir, un int)
list 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í, debes definir una nueva clase que mantenga un int como una variable de instancia
Sus dos ejemplos xint
no funcionan por dos razones diferentes.
El primero no funciona porque self += value
es equivalente a self = self + value
que simplemente reasigna la variable local self
a un objeto diferente (un entero) pero no cambia el objeto original. Realmente no se puede obtener esto
>>> x = xint(10)
>>> x.add(2)
para trabajar con una subclase de int
ya que los enteros son inmutables .
Para que el segundo funcione, puedes definir un método __add__
, como ese:
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''>
amplié tu clase de lista x solo un poco, hice que pudieras encontrar todos los puntos de índice de un número para que puedas extender con múltiples listas a la vez, lo que hace que se inicialice y lo haga para que puedas iterar a través de él
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)