J'essaie de créer une classe qui renvoie une valeur, pas self.
Je vais vous montrer un exemple comparant avec une liste:
>>> l = list()
>>> print(l)
[]
>>> class MyClass:
>>> pass
>>> mc = MyClass()
>>> print mc
<__main__.MyClass instance at 0x02892508>
J'ai besoin que MyClass renvoie une liste, comme le fait list()
, pas les informations d'instance. Je sais que je peux faire une sous-classe de liste. Mais existe-t-il un moyen de le faire sans sous-classement?
Je veux imiter une liste (ou d'autres objets):
>>> l1 = list()
>>> l2 = list()
>>> l1
[]
>>> l2
[]
>>> l1 == l2
True
>>> class MyClass():
def __repr__(self):
return '[]'
>>> m1 = MyClass()
>>> m2 = MyClass()
>>> m1
[]
>>> m2
[]
>>> m1 == m2
False
Pourquoi m1 == m2
Est-il faux? Ceci est la question.
Je suis désolé si je ne réponds pas à vous tous. J'essaie toutes les solutions que tu me donnes. Je ne peux pas utiliser def
, car j'ai besoin d'utiliser des fonctions comme setitem, getitem, etc.
Si ce que vous voulez est un moyen de transformer votre classe en une sorte de liste sans sous-classer list
, alors faites simplement une méthode qui retourne une liste:
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 vous vouliez dire que print MyClass()
imprimera une liste, remplacez simplement __repr__
:
class MyClass():
def __init__(self):
self.value1 = 1
self.value2 = 2
def __repr__(self):
return repr([self.value1, self.value2])
EDIT: Je vois que vous vouliez dire comment faire des objets comparer. Pour cela, vous remplacez la méthode __cmp__
.
class MyClass():
def __cmp__(self, other):
return cmp(self.get_list(), other.get_list())
Je pense que vous êtes très confus quant à ce qui se passe.
En Python, tout est un objet:
[]
(Une liste) est un objet'abcde'
(Une chaîne) est un objet1
(Un entier) est un objetMyClass()
(une instance) est un objetMyClass
(une classe) est aussi un objetlist
(un type - un peu comme une classe) est aussi un objetCe sont toutes des "valeurs" dans le sens où elles sont une chose et non un nom qui fait référence à une chose. (Les variables sont des noms qui font référence à des valeurs.) Une valeur n'est pas quelque chose de différent d'un objet en Python.
Lorsque vous appelez un objet de classe (comme MyClass()
ou list()
), il renvoie une instance de cette classe. (list
est vraiment un type et non une classe, mais je simplifie un peu ici.)
Lorsque vous imprimez un objet (c.-à-d. Obtenez une représentation sous forme de chaîne d'un objet), cet objet est __str__
Ou __repr__
Méthode magique est appelé et la valeur renvoyée est imprimée.
Par exemple:
>>> 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
>>>
Donc, ce que vous demandez, "J'ai besoin que MyClass retourne une liste, comme list (), pas les informations sur l'instance", n'a aucun sens. list()
renvoie une instance de liste. MyClass()
renvoie une instance MyClass. Si vous voulez une instance de liste, obtenez simplement une instance de liste. Si le problème est plutôt à quoi ressemblent ces objets lorsque vous print
ou les regardez dans la console , créez un __str__
Et __repr__
Méthode qui les représente comme vous voulez qu'ils soient représentés.
Encore une fois, __str__
Et __repr__
Sont uniquement pour l'impression , et n'affectent pas l'objet de toute autre manière. Ce n'est pas parce que deux objets ont la même valeur __repr__
Qu'ils sont égaux!
MyClass() != MyClass()
parce que votre classe ne définit pas comment ceux-ci seraient égaux, elle revient donc au comportement par défaut (du type object
), qui est que les objets ne sont égaux qu'eux-mêmes:
>>> m = MyClass()
>>> m1 = m
>>> m2 = m
>>> m1 == m2
True
>>> m3 = MyClass()
>>> m1 == m3
False
Si vous voulez changer cela, utilisez l'une des méthodes magiques de comparaison
Par exemple, vous pouvez avoir un objet qui est égal à tout:
>>> 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
Je pense que vous devriez faire deux choses:
Justifiez pourquoi vous ne sous-classez pas list
si ce que vous voulez ressemble beaucoup à une liste. Si le sous-classement n'est pas approprié, vous pouvez plutôt déléguer à une instance de liste encapsulée:
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)
Cela agira maintenant comme une liste sans être une liste (c'est-à-dire sans sous-classer list
).
>>> c = MyClass()
>>> c.append(1)
>>> c
MyClass([1])
Utilisation __new__
pour renvoyer la valeur d'une classe.
Comme d'autres le suggèrent __repr__
, __str__
ou même __init__
(en quelque sorte) PEUT vous donner ce que vous voulez, mais __new__
sera une solution sémantiquement meilleure pour votre objectif car vous voulez que l'objet réel soit renvoyé et pas seulement sa représentation sous forme de chaîne.
Lisez cette réponse pour plus d'informations sur __str__
et __repr__
https://stackoverflow.com/a/19331543/4985585
class MyClass():
def __new__(cls):
return list() #or anything you want
>>> MyClass()
[] #Returns a true list not a repr or string
class MyClass():
def __init__(self, a, b):
self.value1 = a
self.value2 = b
def __call__(self):
return [self.value1, self.value2]
Essai:
>>> x = MyClass('foo','bar')
>>> x()
['foo', 'bar']
Vous décrivez une fonction, pas une classe.
def Myclass():
return []