0

我在函数、方法之间的交互方面遇到了一些问题,并且不确定如何使用内置函数__str__

首先,我有一个名为 vara 的类,它看起来像:

class vara(object):

    def __init__(self, kod, namn, pris, butikantal):
        self.kod = kod
        self.namn = namn
        self.pris = pris
        self.antal = butikantal

我有一个函数可以为 vara klass 创建一个对象列表,如下所示:

def mina_varor():

  varor_fran_fil = open("varor.txt", "r")
  varulista = []
  for rad in varor_fran_fil:
      varje_vara1 = rad
      varje_vara2 = varje_vara1.split("/")
      varorna = vara(varje_vara2[0], varje_vara2[1], varje_vara2[2], varje_vara2[3])
      varulista.append(varorna)

  return(varulista)

现在我希望能够通过简单地键入对象的“kod”来访问此列表中的单个对象。但我在我的列表中找不到任何“kod”。看起来很奇怪,所以我尝试打印列表,并得到了:

[<__main__.vara object at 0x00000000031503C8>, <__main__.vara object at 0x00000000031507F0>, <__main__.vara object at 0x0000000003150710>, <__main__.vara object at 0x00000000031502B0>, <__main__.vara object at 0x00000000031505F8>, <__main__.vara object at 0x00000000031504E0>]

我查了一下,似乎 python 无法决定如何解释我的列表。我想我需要一种__str__方法来做到这一点,但是__str__如果我想让我的方法看起来像这样打印:

Name: Hat
Price: 150
Quantity: 100
Code: 223

?

4

2 回答 2

1

问题 1:打印容器时未调用 __str__()

并不是 Python 无法解释您的列表,而是它不知道您希望它如何显示。

__str__如果您想做类似的事情,请实施该方法

print(varulista[0])

类似下面的内容会给您带来您对该列表条目的期望:

def __str__(self):
    s  = "Name:    %s\n" % self.namn
    s += "Price:   %s\n" % self.pris
    s += "Quantity:%s\n" % self.antal
    s += "Code:    %s\n" % self.kod

但是,如果您想print(varulista)理解,您还必须实现该__repr__方法,因为varulista它是一个列表,并且在打印它时 Python 会查找该__repr__方法。

但话虽如此,其想法__repr__是能够将其传递回eval()并创建等效对象。因此,您可以采用以下两种方式之一:

1.忽略__repr__()/eval()交互

在这种情况下,只需按照__repr__()您的意愿实施即可。请记住,当它是您正在打印的容器中的项目时,将调用此方法,因此将输出保持在单行可能会有所帮助。只要知道,除非您在__repr__()输出中明确表示对象的状态,否则您将无法使用eval().

2.(首选选项,IMO)__repr__()正确实施,如果您不喜欢容器的外观,就不要打印容器。

如果输出像

[Item{Name:"Hat",Price:150,Quantity:100,Code:223},Item{Name:"Shirt",Price:450,Quantity:10,Code:225}]

由于您必须如何实施,所以太不友好了__repr()__,只是不要打印容器。换句话说,不要使用

print(varulista)

而是使用

for item in varulista: print item

这将调用__str__()您定义的方法,即人性化的方法。

编辑: @bernie 链接到@AlexMartelli 的一个很好的答案,关于两者之间的区别__str____repr__值得链接两次。


问题 2:能够通过其代码访问列表元素

你说

现在我希望能够通过简单地键入对象的“kod”来访问此列表中的单个对象。但我在我的列表中找不到任何“kod”。看起来很奇怪,所以我尝试打印列表,并得到了:

您在这里有两个主要选择。(1) 使用以项目代码为关键字的字典。(2) 使用列表推导在列表中搜索代码。我只会展示 (1),因为我认为这是一个更好的选择。

选项 1:使用键入项目代码的字典

考虑这段代码:

# Define a convenience function to add items to the dictionary
def add_item(d,i): d[i.kod] = i

# Create a new dictionary
items = {}

# Add items to dictionary
add_item(items, vara(223, "Hat", 150, 100))
add_item(items, vara(225, "Shirt", 450, 10))

您现在可以访问items字典中的任何已定义项目,如下所示:

items[223] #<-- This is the "Hat" item
items[225] #<-- This is the "Shirt" item
于 2013-04-05T16:09:35.163 回答
0

你可以这样覆盖__repr__

class vara():
    def __init__(self, kod, namn, pris, butikantal):
        self.kod = kod
        self.namn = namn
        self.pris = pris
        self.antal = butikantal

    def __repr__(self):
        return 'Name: %s\nPrice: %s\nQuantity:%s\nCode: %s\n'\
               % (self.namn, self.pris, self.antal, self.kod)

输出:

>>> print([vara('223', 'Hat', '150', '100'), vara('115', 'Bla', '154', '200')])
[Name: Hat
Price: 150
Quantity:100
Code: 223
, Name: Bla
Price: 154
Quantity:200
Code: 115
]

编辑:

但正如@jedwards 所解释的,这是一种更好的方法来覆盖__str__我所做的相同方式并__repr__单独打印每个对象,而不是打印整个列表。

于 2013-04-05T16:14:56.113 回答