Класс Python, возвращающий значение

Я'пытаюсь создать класс, который возвращает значение, а не self.

Я покажу вам пример, сравнивая со списком:

>>> l = list()
>>> print(l)
[]
>>> class MyClass:
>>>     pass

>>> mc = MyClass()
>>> print mc
<__main__.MyClass instance at 0x02892508>

Мне нужно, чтобы MyClass возвращал список, как это делает list(), а не информацию об экземпляре. Я знаю, что могу создать подкласс list. Но есть ли способ сделать это без создания подкласса?

Я хочу имитировать список (или другие объекты):

>>> l1 = list()
>>> l2 = list()
>>> l1
[]
>>> l2
[]
>>> l1 == l2
True
>>> class MyClass():
def __repr__(self):
    return '[]'

>>> m1 = MyClass()
>>> m2 = MyClass()
>>> m1
[]
>>> m2
[]
>>> m1 == m2
False

Почему m1 == m2 ложно? Вот в чем вопрос.

Извините, если я не отвечаю всем вам. Я пробую все решения, которые вы мне предлагаете. Я не могу использовать def, потому что мне нужно использовать такие функции, как setitem, getitem и т.д.

Я думаю, что вы очень запутались в происходящем.

В Python все является объектом:

  • [] (список) - это объект.
  • 'abcde' (строка) - объект
  • 1 (целое число) - это объект
  • MyClass() (экземпляр) - объект
  • MyClass (класс) также является объектом
  • список (тип - подобно классу) также является объектом

Все они являются "значениями" в том смысле, что они представляют собой вещь, а не имя, которое ссылается на вещь. (Переменные - это имена, которые ссылаются на значения.) Значение не отличается от объекта в Python.

Когда вы вызываете объект класса (например, MyClass() или list()), он возвращает экземпляр этого класса. (На самом деле list - это тип, а не класс, но здесь я немного упрощаю).

Когда вы печатаете объект (т.е. получаете строковое представление объекта), вызывается магический метод __str__ или __repr__ и печатается возвращаемое значение.

Например:

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

Поэтому то, о чем вы просите, "Мне нужно, чтобы MyClass возвращал список, как list(), а не информацию об экземпляре," не имеет никакого смысла. list() возвращает экземпляр списка. MyClass() возвращает экземпляр MyClass. Если вам нужен экземпляр списка, просто получите экземпляр списка. Если вместо этого вопрос заключается в том, как выглядят эти объекты, когда вы печатаете их или смотрите на них в консоли, то создайте метод __str__ и __repr__, который представляет их так, как вы хотите, чтобы они были представлены.

Обновление для нового вопроса о равенстве

Еще раз, __str__ и __repr__ предназначены только для печати, и не влияют на объект никаким другим образом. Если два объекта имеют одинаковое значение __repr__, это не значит, что они равны!

MyClass() != MyClass(), потому что ваш класс не определяет, как они могут быть равны, поэтому он возвращается к поведению по умолчанию (типа object), которое заключается в том, что объекты равны только самим себе:

>>> m = MyClass()
>>> m1 = m
>>> m2 = m
>>> m1 == m2
True
>>> m3 = MyClass()
>>> m1 == m3
False

Если вы хотите изменить это, используйте один из магических методов сравнения

Например, вы можете иметь объект, который равен всему:

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

Я думаю, вы должны сделать две вещи:

  1. Посмотрите на это руководство по использованию магического метода в Python.

  2. Обоснуйте, почему вы не подклассифицируете list, если то, что вам нужно, очень похоже на список. Если подкласс не подходит, вы можете делегировать экземпляр обернутого списка:

     class MyClass(object):
         def __init__(self):
             self._list = []
         def __getattr__(self, name):
             return getattr(self._list, name)
    
         # Методы __repr__ и __str__ создаются автоматически
         # для каждого класса, поэтому если мы хотим делегировать их, мы должны
         # сделать это явно
         def __repr__(self):
             return "MyClass(%s)" % repr(self._list)
         def __str__(self):
             return "MyClass(%s)" % str(self._list)

    Теперь список будет вести себя как список, не будучи списком (т.е. без подкласса list).

     >>> c = MyClass()
     >>> c.append(1)
     >>> c
     MyClass([1])
Комментарии (3)
Решение

Если вам нужен способ превратить ваш класс в подобие списка без подкласса list, то просто сделайте метод, возвращающий список:

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

Если вы хотели, чтобы print MyClass() выводил список, просто переопределите __repr__:

class MyClass():        
    def __init__(self):
        self.value1 = 1
        self.value2 = 2

    def __repr__(self):
        return repr([self.value1, self.value2])

EDIT: Я вижу, вы имели в виду, как сделать объекты сравниваемыми. Для этого вы переопределяете метод __cmp__.

class MyClass():
    def __cmp__(self, other):
        return cmp(self.get_list(), other.get_list())
Комментарии (3)

Вы описываете функцию, а не класс.

def Myclass():
    return []
Комментарии (3)