Как использовать getattr в сочетании с форматированием строки dict? - PullRequest
0 голосов
/ 02 июля 2018

У меня есть класс структуры данных и класс форматирования таблицы, в котором я хочу отформатировать файл и вывести его. Мне нужна гибкость создания форматеров на лету, если необходимо изменить вывод.

class Row(object):
    __slots__ = ('date', 'item', 'expiration', 'price')
    def __init__(self, date, item, expiration, price=None):
        self.date = date
        self.item = item
        self.expiration = expiration
        self.price = ""

        if price:
            self.price = price

class Formatter(object):
    def row(self, rowdata):
        for item in rowdata:
            print('<obj date="{date}" item="{item}" exp="{expiration}" price="{price}" />\n').format(**item)


def print_table(objects, colnames, formatter):
    for obj in objects:
        rowdata = [str(getattr(obj, colname)) for colname in colnames]
        formatter.row(rowdata)

Я так называю:

data = [Row("20180101", "Apples", "20180201", 1.50),
         Row("20180101", "Pears", "20180201", 1.25)]

formatter = Formatter()
print_table(data, ['date','item','expiration','price'], formatter)

Я ожидаю увидеть:

<obj date="20180101" item="Apples" exp="20180201" price="1.50" /> <obj date="20180101" item="Pears" exp="20180201" price="1.25" />

В настоящее время я получаю следующую ошибку: TypeError: format() argument after ** must be a mapping, not str

Может кто-нибудь помочь с этим? Спасибо

Ответы [ 2 ]

0 голосов
/ 02 июля 2018

**item недопустимо, потому что оператор ** ожидает, что именованная переменная является словарем ( mapping ), и вы не указали это (элемент является строкой). Таким образом, вам необходимо преобразовать item в словарь с правильными парами ключ / значение, которые вы хотите использовать в выражении формата.

0 голосов
/ 02 июля 2018

Фиксированный код:

class Formatter(object):
    def row(self, rowdata):
        print('<obj date="{date}" item="{item}" exp="{expiration}" price="{price}" />\n'.format(**rowdata))


def print_table(objects, colnames, formatter):
    for obj in objects:
        rowdata = {colname: str(getattr(obj, colname)) for colname in colnames}
        formatter.row(rowdata)

У вас было 3 проблемы:

  1. Вы рассматривали rowdata как список элементов, в то время как rowdata должны быть одиночными отображение между именем столбца и данными
  2. Вы не создали отображение, только результаты. {colname: str(getattr(obj, colname)) for colname in colnames} создает отображение между именем и атрибутом. Затем вы можете передать его на .format(), и он будет полностью работать.
  3. Вы использовали format() для функции print(). Вы должны использовать его на строку внутри.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...