Valor de retorno de la clase Python
Estoy intentando crear una clase que devuelva un valor, no uno mismo.
Te mostraré un ejemplo comparándolo con una lista:
>>> l = list()
>>> print(l)
[]
>>> class MyClass:
>>> pass
>>> mc = MyClass()
>>> print mc
<__main__.MyClass instance at 0x02892508>
Necesito que MyClass devuelva una lista, comolist()
lo hace, no la información de la instancia. Sé que puedo hacer una subclase de lista. ¿Pero hay alguna manera de hacerlo sin subclasificar?
Quiero imitar una lista (u otros objetos):
>>> l1 = list()
>>> l2 = list()
>>> l1
[]
>>> l2
[]
>>> l1 == l2
True
>>> class MyClass():
def __repr__(self):
return '[]'
>>> m1 = MyClass()
>>> m2 = MyClass()
>>> m1
[]
>>> m2
[]
>>> m1 == m2
False
Por que esm1 == m2
falso? Esta es la pregunta.
Lo siento si no les respondo a todos. Estoy probando todas las soluciones que me das. No puedo usarlo def
porque necesito usar funciones como setitem, getitem, etc.
Creo que estás muy confundido acerca de lo que está ocurriendo.
En Python todo es un objeto:
[]
(una lista) es un objeto'abcde'
(una cadena) es un objeto1
(un número entero) es un objetoMyClass()
(una instancia) es un objetoMyClass
(una clase) también es un objetolist
(un tipo, muy parecido a una clase) también es un objeto
Todos son "valores" en el sentido de que son una cosa y no un nombre que se refiere a una cosa. (Las variables son nombres que se refieren a valores). Un valor no es algo diferente de un objeto en Python.
Cuando llamas a un objeto de clase (como MyClass()
o list()
), devuelve una instancia de esa clase. ( list
Es realmente un tipo y no una clase, pero estoy simplificando un poco aquí).
Cuando imprime un objeto (es decir, obtiene una representación de cadena de un objeto), se llama al método mágico __str__
o de ese objeto y se imprime el valor devuelto.__repr__
Por ejemplo:
>>> class MyClass(object):
... def __str__(self):
... return "MyClass([])"
... def __repr__(self):
... return "I am an instance of MyClass at address "+hex(id(self))
...
>>> m = MyClass()
>>> print m
MyClass([])
>>> m
I am an instance of MyClass at address 0x108ed5a10
>>>
Entonces, lo que estás pidiendo, "Necesito que MyClass devuelva una lista, como list(), no la información de la instancia", no tiene ningún sentido. list()
devuelve una instancia de lista. MyClass()
devuelve una instancia de MyClass. Si desea una instancia de lista, simplemente obtenga una instancia de lista. Si, en cambio, el problema es cómo se ven estos objetos cuando print
los miras o los miras en la consola , entonces crea un método __str__
and __repr__
que los represente como quieres que se representen.
Actualización para nueva pregunta sobre igualdad
Una vez más, __str__
son __repr__
sólo para impresión y no afectan al objeto de ninguna otra manera. ¡El hecho de que dos objetos tengan el mismo __repr__
valor no significa que sean iguales!
MyClass() != MyClass()
debido a que su clase no define cómo serían iguales, vuelve al comportamiento predeterminado (del object
tipo), que es que los objetos solo son iguales a sí mismos:
>>> m = MyClass()
>>> m1 = m
>>> m2 = m
>>> m1 == m2
True
>>> m3 = MyClass()
>>> m1 == m3
False
Si desea cambiar esto, utilice uno de los métodos mágicos de comparación.
Por ejemplo, puedes tener un objeto que sea igual a todo:
>>> class MyClass(object):
... def __eq__(self, other):
... return True
...
>>> m1 = MyClass()
>>> m2 = MyClass()
>>> m1 == m2
True
>>> m1 == m1
True
>>> m1 == 1
True
>>> m1 == None
True
>>> m1 == []
True
Creo que deberías hacer dos cosas:
- Eche un vistazo a esta guía sobre el uso de métodos mágicos en Python .
Justifique por qué no está subclasificando
list
si lo que quiere es muy parecido a una lista. Si la creación de subclases no es apropiada, puede delegar en una instancia de lista ajustada:class MyClass(object): def __init__(self): self._list = [] def __getattr__(self, name): return getattr(self._list, name) # __repr__ and __str__ methods are automatically created # for every class, so if we want to delegate these we must # do so explicitly def __repr__(self): return "MyClass(%s)" % repr(self._list) def __str__(self): return "MyClass(%s)" % str(self._list)
Esto ahora actuará como una lista sin ser una lista (es decir, sin subclases
list
).>>> c = MyClass() >>> c.append(1) >>> c MyClass([1])
Si lo que desea es una forma de convertir su clase en una especie de lista sin subclases list
, simplemente cree un método que devuelva una lista:
def MyClass():
def __init__(self):
self.value1 = 1
self.value2 = 2
def get_list(self):
return [self.value1, self.value2...]
>>>print MyClass().get_list()
[1, 2...]
Si quiso decir que print MyClass()
imprimirá una lista, simplemente anule __repr__
:
class MyClass():
def __init__(self):
self.value1 = 1
self.value2 = 2
def __repr__(self):
return repr([self.value1, self.value2])
EDITAR: Veo que quisiste decir cómo hacer que los objetos se comparen . Para eso, anula el __cmp__
método.
class MyClass():
def __cmp__(self, other):
return cmp(self.get_list(), other.get_list())