Как использовать pprint для печати объекта, используя встроенный метод __str__(self)?
У меня есть скрипт Python, который обрабатывает файл.txt, который содержит информацию об использовании отчета. Я хотел бы найти способ чистой печати атрибутов объекта с помощью функции pprint pprint(vars(object)).
Скрипт читает файл и создает экземпляры класса Report. Вот класс.
class Report(object):
def __init__(self, line, headers):
self.date_added=get_column_by_header(line,headers,"Date Added")
self.user=get_column_by_header(line,headers,"Login ID")
self.report=get_column_by_header(line,headers,"Search/Report Description")
self.price=get_column_by_header(line,headers,"Price")
self.retail_price=get_column_by_header(line,headers,"Retail Price")
def __str__(self):
from pprint import pprint
return str(pprint(vars(self)))
Я хотел бы иметь возможность печатать экземпляры отчета чисто a-la-pprint.
for i,line in enumerate(open(path+file_1,'r')):
line=line.strip().split("|")
if i==0:
headers=line
if i==1:
record=Report(line,headers)
print record
Когда я звоню
print record
для одного экземпляра Report это то, что я получаю в оболочке.
{'date_added': '1/3/2012 14:06',
'price': '0',
'report': 'some_report',
'retail_price': '0.25',
'user': 'some_username'}
None
У меня вопрос двоякий.
Во-первых, это хороший / желаемый способ чистой печати атрибутов объекта? Есть ли лучший способ сделать это с или без pprint?
Во-вторых, почему
None
распечатать на оболочку в конце? Я запутался, откуда это идет.
Спасибо за любые советы.
6 ответов
pprint
это просто еще одна форма печати. Когда ты сказал pprint(vars(self))
он печатает переменные в стандартный вывод и ничего не возвращает, потому что это функция void. Так что, когда вы бросаете его в строку, получается None
(возвращается pprint
) в строку, которая затем печатается из исходного оператора печати. Я бы предложил изменить ваш принт на pprint
или переопределить печать как печать, если это все, для чего вы ее используете.
def __str__(self):
from pprint import pprint
return str(vars(self))
for i,line in enumerate(open(path+file_1,'r')):
line = line.strip().split("|")
if i == 0:
headers = line
if i == 1:
record = Report(line,headers)
pprint record
Одна альтернатива - использовать форматированный вывод:
def __str__(self):
return "date added: %s\nPrice: %s\nReport: %s\nretail price: %s\nuser: %s" % tuple([str(i) for i in vars(self).values()])
Надеюсь, это помогло
Решение Дэна просто неверно, а Исмаил неполон.
__str__()
не называется,__repr__()
называется.__repr__()
должен вернуть строку, как это делает pformat.- обычно печатает отступ только на 1 символ и пытается сохранить строки. Если вы пытаетесь выяснить структуру, установите ширину низкой и отступа высокой.
Вот пример
class S:
def __repr__(self):
from pprint import pformat
return pformat(vars(self), indent=4, width=1)
a = S()
a.b = 'bee'
a.c = {'cats': ['blacky', 'tiger'], 'dogs': ['rex', 'king'] }
a.d = S()
a.d.more_c = a.c
print(a)
Это печатает
{ 'b': 'bee',
'c': { 'cats': [ 'blacky',
'tiger'],
'dogs': [ 'rex',
'king']},
'd': { 'more_c': { 'cats': [ 'blacky',
'tiger'],
'dogs': [ 'rex',
'king']}}}
Что не идеально, но сносно.
pprint.pprint
не возвращает строку; фактически он выполняет печать (по умолчанию это стандартный вывод, но вы можете указать выходной поток). Поэтому, когда вы пишете print record
, record.__str__()
вызывается, который звонит pprint
, который возвращает None
, str(None)
является 'None'
и это получает print
Эд, вот почему вы видите None
,
Вы должны использовать pprint.pformat
вместо. (В качестве альтернативы, вы можете передать StringIO
экземпляр для pprint
.)
Я думаю, что beeprint это то, что вам нужно.
Просто pip install beeprint
и измените свой код на:
def __str__(self):
from beeprint import pp
return pp(self, output=False)
Для красивых печатных объектов, которые содержат другие объекты и т. Д. pprint
недостаточно. Попробуйте IPython lib.pretty, который основан на модуле Ruby.
from IPython.lib.pretty import pprint
pprint(complex_object)
Способ @Anyany Pan - лучший.
Делюсь реальным кейсом, когда имею дело с ресурсом Azure
в ресурсах AWS я могу легко распечатать сведения о ресурсе, но это не работает с ресурсом Azure. Потому что они разных типов.
from azure.identity import AzureCliCredential
from azure.mgmt.compute import ComputeManagementClient
#from pprint import pprint
from beeprint import pp
import os
# Acquire a credential object using CLI-based authentication.
credential = AzureCliCredential()
# Retrieve subscription ID from environment variable.
subscription_id = os.environ["AZURE_SUBSCRIPTION_ID"]
compute_client = ComputeManagementClient(credential, subscription_id)
vm_list = compute_client.virtual_machines.list_all()
for vm in vm_list:
type(vm)
# pprint(vm) # doesn't work for Azure resource
pp(vm)
вывод для справки по beeprint
<class 'azure.mgmt.compute.v2020_12_01.models._models_py3.VirtualMachine'>
instance(VirtualMachine):
_attribute_map: {
'additional_capabilities': {
'key': 'properties.additionalCapabilities',
'type': 'AdditionalCapabilities',
},
'availability_set': {
'key': 'properties.availabilitySet',
'type': 'SubResource',
},
'billing_profile': {
'key': 'properties.billingProfile',
...
вывод поpprint
<class 'azure.mgmt.compute.v2020_12_01.models._models_py3.VirtualMachine'>
<azure.mgmt.compute.v2020_12_01.models._models_py3.VirtualMachine object at 0x1047cf4f0>
<class 'azure.mgmt.compute.v2020_12_01.models._models_py3.VirtualMachine'>
<azure.mgmt.compute.v2020_12_01.models._models_py3.VirtualMachine object at 0x1047cf5b0>