How do I use getattr in conjunction with dict string formatting?


How do I use getattr in conjunction with dict string formatting?



I have a data structure class and a table formatting class in which I want to format a file and output it. I want the flexibility of creating formatters on the fly if the output needs to be changed.


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)



I'm calling this like so:


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

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



What I'm expecting to see is:



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


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



I am currently getting the following error:
TypeError: format() argument after ** must be a mapping, not str


TypeError: format() argument after ** must be a mapping, not str



Can anyone help with this? Thanks





You don't seem to create a dict at any point in this code, yet you're trying to use rowdata as if its elements are dicts.
– user2357112
Jul 2 at 20:32



rowdata




2 Answers
2



Fixed code:


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)



You had 3 problems:


{colname: str(getattr(obj, colname)) for colname in colnames}


.format()


format()


print()



**item is invalid because the ** operator expects the named variable to be a dictionary (a mapping), and you have not provided that (item is a string). Thus, you need to convert item into a dictionary with the proper key/value pairs that you want in your format statement.


**item


**


item






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

api-platform.com Unable to generate an IRI for the item of type

How to set up datasource with Spring for HikariCP?

Display dokan vendor name on Woocommerce single product pages