Я'пытаюсь создать класс, который возвращает значение, а не 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
Я думаю, вы должны сделать две вещи:
Посмотрите на это руководство по использованию магического метода в Python.
Обоснуйте, почему вы не подклассифицируете 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])
Если вам нужен способ превратить ваш класс в подобие списка без подкласса 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())
Вы описываете функцию, а не класс.
def Myclass():
return []