Python __str__ для объекта
При попытке выяснить, как работает BeautifulSoup, я случайно узнал метод __str__
(я новичок в python). Поэтому, если я не ошибочно понял, то метод __str__
помогает определить, каким образом класс будет представлен, если будет распечатан. Например:
class Foo:
def __str__(self):
return "bar"
>>> x = Foo()
>>> print x
bar
Правильно? Поэтому, утверждая, что я прав, можно ли переопределить метод __str__
списка словарей? Я имею в виду, что в классе Foo у вас есть:
class Foo:
def __init__(self):
self.l = [{"Susan": ("Boyle", 50, "alive")}, {"Albert": ("Speer", 106, "dead")}]
Теперь можно ли получить следующий результат?
>>> x = Foo()
>>> print x.l
"Susan Boyle is 50 and alive. Albert Speer is 106 and dead."
ИЗМЕНИТЬ
С учетом решения agf, как я могу получить доступ к словарю еще раз? Я имею в виду, если я определяю метод __str__
, то, видимо, я должен определить что-то другое, чтобы получить словарь как есть. Пожалуйста, рассмотрите следующий пример:
class PClass(dict):
def __str__(self):
# code to return the result that I want
class Foo:
def __init__(self):
self.l = PClass({"Susan": ["Boyle", ........ })
>>> x = Foo()
>>> print x.l
# result that works great
>>> y = x.l["Susan"] # this would not work. How can I achieve it?
Ответы
Ответ 1
Вам нужно подклассифицировать элемент, который вы довольно печатаете.
from itertools import chain
class PrintableList(list): # for a list of dicts
def __str__(self):
return '. '.join(' '.join(str(x) for x in
chain.from_iterable(zip((item[0], 'is', 'and'), item[1])))
for item in (item.items()[0] for item in self)) + '.'
class PrintableDict(dict): # for a dict
def __str__(self):
return '. '.join(' '.join(str(x) for x in
chain.from_iterable(zip((item[0], 'is', 'and'), item[1])))
for item in self.iteritems()) + '.'
class Foo:
def __init__(self):
self.d = PrintableDict({"Susan": ("Boyle", 50, "alive"),
"Albert": ("Speer", 106, "dead")})
class Bar:
def __init__(self):
self.l = PrintableList([{"Susan": ("Boyle", 50, "alive")},
{"Albert": ("Speer", 106, "dead")}])
foo = Foo()
print self.d
bar = Bar()
print self.l
Ответ 2
Другой альтернативой является переопределение __getattribute__
, которое позволяет настроить способ возврата атрибутов:
class Foo(object):
def __init__(self):
self.l = [{"Susan": ("Boyle", 50, "alive")}, {"Albert": ("Speer", 106, "dead")}]
def __getattribute__(self, name):
return PrintableList(l)
attr = super(Foo, self).__getattribute__(name)
items = sum([x.items() for x in attr], [])
return ' '.join([' '.join([k, v[0], 'is', str(v[1]), 'and', v[2] + '.']) for k,v in items])
>>> f = Foo()
>>> print f.l
<<< Susan Boyle is 50 and alive. Albert Speer is 106 and dead.
Ответ 3
Вы можете определить __str__
для вашего класса Foo, чтобы вернуть то, что вы хотите:
class Foo():
def __init__(self):
self.l = [{"Susan": ("Boyle", 50, "alive")}, {"Albert": ("Speer", 106, "
dead")}]
def __str__(self):
ret_str = ""
for d in self.l:
for k in d:
ret_str += "".join([k, " ", d[k][0], " is ", str(d[k][1]), " and
", d[k][2], ". "])
return ret_str
foo = Foo()
print foo
приводит к:
Сьюзен Бойл - 50 лет и жив. Альберт Шпеер - 106 лет и умер.