python类返回值

Python class returning value

我试图创建一个返回值的类,而不是self。

我将向您展示一个与列表比较的示例:

1
2
3
4
5
6
7
8
9
>>> l = list()
>>> print(l)
[]
>>> class MyClass:
>>>     pass

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

我需要MyClass返回一个列表,就像list()返回的那样,而不是实例信息。我知道我可以创建列表的子类。但是有没有一种方法可以不用子类化来完成它呢?

我想模仿一个列表(或其他对象):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
>>> 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类也是一个对象
  • list(一个类型——很像一个类)也是一个对象

它们都是"价值观",从某种意义上说,它们是一个事物,而不是指一个事物的名称。(变量是引用值的名称。)值与Python中的对象没有什么不同。

当调用一个类对象(如MyClass()list()时,它返回该类的一个实例。(list实际上是一种类型,而不是类,但我在这里简化了一点。)

打印对象(即获取对象的字符串表示形式)时,将调用该对象的__str____repr__magic方法并打印返回值。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
>>> 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类型),也就是说,对象只等于它们自己:

1
2
3
4
5
6
7
8
>>> m = MyClass()
>>> m1 = m
>>> m2 = m
>>> m1 == m2
True
>>> m3 = MyClass()
>>> m1 == m3
False

如果你想改变这一点,使用比较魔术的方法之一

例如,您可以拥有一个等于所有内容的对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
>>> 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子类化。如果子类化不合适,则可以委托给包装列表实例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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)

    这现在就像一个没有列表的列表(也就是说,没有子类化list)。

    1
    2
    3
    4
    >>> c = MyClass()
    >>> c.append(1)
    >>> c
    MyClass([1])

  • 如果您想要的是一种将类转换为列表的方法,而不需要对list进行子类化,那么只需创建一个返回列表的方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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__即可:

    1
    2
    3
    4
    5
    6
    7
    class MyClass():        
        def __init__(self):
            self.value1 = 1
            self.value2 = 2

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

    编辑:我明白你的意思是如何使物体相互比较。为此,您将重写__cmp__方法。

    1
    2
    3
    class MyClass():
        def __cmp__(self, other):
            return cmp(self.get_list(), other.get_list())


    使用__new__返回类的值。

    正如其他人所说,__repr____str__,甚至__init__,可以给你想要的,但__new__对于你的目的来说是一个语义上更好的解决方案,因为你想返回实际的对象,而不仅仅是它的字符串表示。

    阅读此答案,了解更多有关__str____repr__的信息。https://stackoverflow.com/a/19331543/4985585

    1
    2
    3
    4
    5
    6
    class MyClass():
        def __new__(cls):
            return list() #or anything you want

    >>> MyClass()
    []   #Returns a true list not a repr or string


    1
    2
    3
    4
    5
    6
    7
    class MyClass():
        def __init__(self, a, b):
            self.value1 = a
            self.value2 = b

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

    测试:

    1
    2
    3
    >>> x = MyClass('foo','bar')
    >>> x()
    ['foo', 'bar']


    您描述的是函数,而不是类。

    1
    2
    def Myclass():
        return []