Как использовать 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()])

Надеюсь, это помогло

Решение Дэна просто неверно, а Исмаил неполон.

  1. __str__() не называется, __repr__() называется.
  2. __repr__() должен вернуть строку, как это делает pformat.
  3. обычно печатает отступ только на 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>
Другие вопросы по тегам