web-dev-qa-db-fra.com

Python classe renvoyant une valeur

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.

13
Harry Hache

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())
18
lolopop

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 objet
  • 1 (Un entier) est un objet
  • MyClass() (une instance) est un objet
  • MyClass (une classe) est aussi un objet
  • list (un type - un peu comme une classe) est aussi un objet

Ce 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.

Mise à jour pour une nouvelle question sur l'égalité

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:

  1. Jetez un œil à ce guide d'utilisation des méthodes magiques en Python .
  2. 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])
    
27
Francis Avila

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
7
Kashif Siddiqui
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']
6
Qazerowl

Vous décrivez une fonction, pas une classe.

def Myclass():
    return []
4
Ali Afshar