Python 类返回值

问题描述 投票:0回答:6

我正在尝试创建一个返回值而不是 self 的类。

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

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

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

我需要 MyClass 返回一个列表,就像

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 class return
6个回答
57
投票

我认为你对正在发生的事情感到非常困惑。

在Python中,一切都是对象:

  • []
    (列表)是一个对象
  • 'abcde'
    (字符串)是一个对象
  • 1
    (整数)是一个对象
  • MyClass()
    (实例)是一个对象
  • MyClass
    (类)也是一个对象
  • list
    (类型——很像类)也是一个对象

它们都是“值”,因为它们是一个事物,而不是指代一个事物的名称。 (变量是指代值的名称。)值与 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 实例。如果您想要一个列表实例,只需获取一个列表实例即可。如果问题是 当您
print
或在控制台中查看它们时,这些对象会是什么样子
,则创建一个
__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__ 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
    )。

    >>> c = MyClass()
    >>> c.append(1)
    >>> c
    MyClass([1])
    

47
投票

如果你想要的是一种将你的类变成列表而不需要子类化的方法

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

编辑: 我明白你的意思是如何制作对象比较。为此,您可以重写

__cmp__
方法。

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

19
投票

使用

__new__
从类返回值。

正如其他人建议的那样,

__repr__
__str__
甚至
__init__
(以某种方式)可以给你你想要的东西,但是
__new__
将是一个语义上更好的解决方案,因为你希望返回实际的对象而不是只是它的字符串表示形式。

阅读此答案,了解有关

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

11
投票
class MyClass():
    def __init__(self, a, b):
        self.value1 = a
        self.value2 = b

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

测试:

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

4
投票

您正在描述一个函数,而不是一个类。

def Myclass():
    return []

0
投票

对我来说有效的建议是在课堂上创建小数字列表的

__call__

import itertools
    
class SmallNumbers:
    def __init__(self, how_much):
        self.how_much = int(how_much)
        self.work_list = ['₀', '₁', '₂', '₃', '₄', '₅', '₆', '₇', '₈', '₉']
        self.generated_list = ['₀', '₁', '₂', '₃', '₄', '₅', '₆', '₇', '₈', '₉']
        start = 10
        end = 100
        for cmb in range(2, len(str(self.how_much)) + 1):
            self.ListOfCombinations(is_upper_then=start, is_under_then=end, combinations=cmb)
            start *= 10
            end *= 10

    def __call__(self, number, *args, **kwargs):
        return self.generated_list[number]

    def ListOfCombinations(self, is_upper_then, is_under_then, combinations):
        multi_work_list = eval(str('self.work_list,') * combinations)
        nbr = 0
        for subset in itertools.product(*multi_work_list):
            if is_upper_then <= nbr < is_under_then:
                self.generated_list.append(''.join(subset))
                if self.how_much == nbr:
                    break
            nbr += 1

并运行它:

if __name__ == '__main__':
        sm = SmallNumbers(56)
        print(sm.generated_list)
        print(sm.generated_list[34], sm.generated_list[27], sm.generated_list[10])
        print('The Best', sm(15), sm(55), sm(49), sm(0))

结果

['₀', '₁', '₂', '₃', '₄', '₅', '₆', '₇', '₈', '₉', '₁₀', '₁₁', '₁₂', '₁₃', '₁₄', '₁₅', '₁₆', '₁₇', '₁₈', '₁₉', '₂₀', '₂₁', '₂₂', '₂₃', '₂₄', '₂₅', '₂₆', '₂₇', '₂₈', '₂₉', '₃₀', '₃₁', '₃₂', '₃₃', '₃₄', '₃₅', '₃₆', '₃₇', '₃₈', '₃₉', '₄₀', '₄₁', '₄₂', '₄₃', '₄₄', '₄₅', '₄₆', '₄₇', '₄₈', '₄₉', '₅₀', '₅₁', '₅₂', '₅₃', '₅₄', '₅₅', '₅₆']
₃₄ ₂₇ ₁₀
The Best ₁₅ ₅₅ ₄₉ ₀
© www.soinside.com 2019 - 2024. All rights reserved.