Python中的类和对象引用,不了解如何返回值

2024-09-28 13:15:31 发布

您现在位置:Python中文网/ 问答频道 /正文

编辑:由于我询问如何正确打印一个类项目,这被标记为重复。这是我问题的一部分,是的,但我更困惑于对象实例的交互以及一般情况下引用事物的方式。这很有帮助。另外,我本来应该这样做的,但我已经包括了MITx(在线mooc)的解决方案,用于我一直在学习的0/1背包问题的“bag”创建。这可能更清楚地说明了为什么他们编写了classbuildItems函数

我现在已经阅读了大量教程,试图理解python中的对象引用和类实例的创建,但我不明白为什么我会得到这个我没有看到的特定输出

我有一个程序片段:

class Item(object):
     def __init__(self, n, v, w):
         self.name = n
         self.value = float(v)
         self.weight = float(w)
     def getName(self):
         return self.name
     def getValue(self):
         return self.value
     def getWeight(self):
         return self.weight
     def __str__(self):
         return '<' + self.name + ', ' + str(self.value) + ', '\
                    + str(self.weight) + '>'


def buildItems():
    return [Item(n,v,w) for n,v,w in (('clock', 175, 10),
                                      ('painting', 90, 9),
                                      ('radio', 20, 4),
                                      ('vase', 50, 2),
                                      ('book', 10, 1),
                                      ('computer', 200, 20))]

编辑(代码的其余部分)

def yieldAllCombos(items):
    N = len(items)
    # Enumerate the 3**N possible combinations
    for i in range(3**N):
        bag1 = []
        bag2 = []
        for j in range(N):
            if (i // (3 ** j)) % 3 == 1:
                bag1.append(items[j])
            elif (i // (3 ** j)) % 3 == 2:
                bag2.append(items[j])
        yield (bag1, bag2)

编辑结束

这些是我一直在研究的一个背包入门问题的一部分,这个问题让我意识到我不理解类和对象实例到底发生了什么

如果我理解buildItems(),它将创建Item类的6个不同实例,并返回包含这些实例的列表

尝试做一些简单的事情,我想在buildItems()函数中创建一个包含这些默认值的列表。为了测试,我这样做:

myitems = buildItems()
print(myitems)

我希望看到这样的列表:

[[clock,175,10], [painting,90,9], [radio,20,4], [vase, 50, 2], [book, 10, 1], [computer, 200, 20]]

但我得到的回报是:

[[<__main__.Item object at 0x7f2ce7819650>, <__main__.Item object at 0x7f2ce67cfa90>, <__main__.Item object at 0x7f2ceb766a50>, <__main__.Item object at 0x7f2ceb766d10>, <__main__.Item object at 0x7f2cebc9ba90>, <__main__.Item object at 0x7f2ceb4ec210>]]

我意识到这是实际的对象,内存中有位置,对吗?返回实际数据需要做什么?此外,我还尝试将buildItems放在类定义的内部和外部,如果将其放在内部,则需要将self包含在def buildItems(self)中,但如果这样做,会让我更加困惑:

items=Item.buildItems()

我得到:

TypeError: buildItems() missing 1 required positional argument: 'self'

我的理解是,“自我”总是隐含的。如果我这样做:

items = Item.buildItems(self)

它显然返回一个"error 'self' is undefined"

我只是很困惑,我似乎不明白这个例子和我最初学习课程时有什么不同

如果有人能帮我解决这个问题,我将不胜感激,我觉得这会在概念上给我带来很多启发


Tags: 对象实例nameself编辑returnobjectvalue
3条回答

问题的一部分是如何开发如下代码

myitems = buildItems()
print(myitems)

生成如下所示的输出

[[clock,175,10],
[painting,90,9], 
[radio,20,4], 
[vase, 50, 2], 
[book, 10, 1], 
[computer, 200, 20]]

下面是生成类似输出的代码片段

myitems = buildItems()
for i in range(len(myitems)):
    print(str(myitems[i]))

Item对象中使用__str__定义的输出

<clock, 175.0, 10.0>
<painting, 90.0, 9.0>
<radio, 20.0, 4.0>
<vase, 50.0, 2.0>
<book, 10.0, 1.0>
<computer, 200.0, 20.0>

参考资料:

您已经在路上了,并且已经定义了一个__str__(self)方法。这将覆盖默认的对象__str__方法。因此,每当您打印项目时,它都会以您定义的格式打印,实际上,每当您尝试以字符串方式使用类时,它都会调用此方法

但是,当您将它们放在列表中并打印列表时,对象表示将调用__repr__方法。这通常意味着表示如何创建此实例,但可以是您喜欢的任何内容

如果您只想返回相同的字符串表示形式,您可以这样做

 def __repr__(self):
     return self.__str__()

如果您希望您的输出像您在问题中显示的那样,看起来像一个列表

 def __repr__(self):
     return str([self.name, self.value, self.weight])

如果您想在构建类时表示它

 def __repr__(self):
     return self.__class__.__name__ + "(" + ",".join((self.name, str(self.value), str(self.weight))) + ")"

输出

[<clock, 175.0, 10.0>, <painting, 90.0, 9.0>, <radio, 20.0, 4.0>, <vase, 50.0, 2.0>, <book, 10.0, 1.0>, <computer, 200.0, 20.0>]
[[clock,175.0,10.0], [painting,90.0,9.0], [radio,20.0,4.0], [vase,50.0,2.0], [book,10.0,1.0], [computer,200.0,20.0]]
[Item(clock,175.0,10.0), Item(painting,90.0,9.0), Item(radio,20.0,4.0), Item(vase,50.0,2.0), Item(book,10.0,1.0), Item(computer,200.0,20.0)]

因此,您需要重写__repr__方法,但它如何呈现自己实际上取决于您

<这里有几个事情要考虑:

  1. 函数buildItems不是Item类的一部分。这意味着调用Item.buildItems()不起作用。这将给出错误AttributeError: type object 'Item' has no attribute 'buildItems'。您提供的错误消息可能是因为缩进实际上不同

  2. 如果实际将项目转换为字符串,则将调用函数__str__(self),如下所示:

    myitems = buildItems()
    print(str(myitems[0])) # results in '<clock, 175.0, 10.0>'
    
  3. 但是,您正在调用对象列表的print,在那里__repr__(self)函数将用于为列表中的每个元素生成字符串。因此,您需要如下重写__repr__(self)函数:

    class Item(object): 
          def __init__(self, n, v, w): 
              self.name = n 
              self.value = float(v) 
              self.weight = float(w) 
          def getName(self): 
              return self.name 
          def getValue(self): 
              return self.value 
          def getWeight(self): 
              return self.weight 
          def __str__(self): 
              return '<' + self.name + ', ' + str(self.value) + ', '\ 
                         + str(self.weight) + '>' 
          def __repr__(self): 
              return str([self.name, self.value,self.weight])
    

编辑:

这将产生您想要的输出。然而,这与@ShadowRanger的评论中提到的__repr__函数背后的意图不一致。通过复制粘贴到终端中实现输出的更好方法如下:

def __repr__(self): 
    return self.__class__.__name__+ repr((self.name, self.value,self.weight))

`

相关问题 更多 >

    热门问题