Reputation: 53
I have a list of dicts and I need to access dicts values as attributes.
My code:
class Comments:
def __init__(self):
self.comments = [{'id': 1, 'title': 'bla'},
{'id': 2, 'title': 'bla2'},
{'id': 3, 'title': 'bla3'}]
def __iter__(self):
return iter(self.comments)
So, when I write something like:
comment_list = Comments()
for comment in comment_list:
print comment['id']
It works.
But I want to use attributes as comment.id
instead of comment['id']
.
How to realize that?
Upvotes: 2
Views: 135
Reputation: 123491
You can make the comments instances of a dictionary subclass that allows normal access as well as dotted attribute-style access. There are several ways of implementing it, but the following is one of the simplest, which is to make the each instance its own __dict__
:
class Comment(dict):
def __init__(self, *args, **kwargs):
super(Comment, self).__init__(*args, **kwargs)
self.__dict__ = self
class Comments(object):
def __init__(self):
self.comments = [Comment({'id': 1, 'title': 'bla'}),
Comment({'id': 2, 'title': 'bla2'}),
Comment({'id': 3, 'title': 'bla3'})]
def __iter__(self):
return iter(self.comments)
comment_list = Comments()
for comment in comment_list:
print(comment.id)
Note that Comment
dictionaries can be created any of the many ways regular dictionaries can, so in addition to what is shown above, the instances in the comments
list could have been created like this which uses keywords to define their contents:
class Comments(object):
def __init__(self):
self.comments = [Comment(id=1, title='bla'),
Comment(id=2, title='bla2'),
Comment(id=3, title='bla3')]
Upvotes: 0
Reputation: 1358
class AttrDict(dict):
def __init__(self, *args, **kwargs):
super(AttrDict, self).__init__(*args, **kwargs)
self.__dict__ = self
class Comments:
def __init__(self):
self.comments = [{'id': 1, 'title': 'bar'},
{'id': 2, 'title': 'foo'},
{'id': 3, 'title': 'spam'}]
def __iter__(self):
return iter(self.comments)
comment_list = Comments()
for comment in comment_list:
print(AttrDict(comment).id)
AttrDict used from here.
Upvotes: 0
Reputation: 51857
Another approach for completeness - use a namedtuple
.
from collections import namedtuple
Comment = namedtuple('Comment', ('id', 'title'))
comments = [Comment(42, 'What is the answer to life, the universe, and everything?'),
Comment(13, 'What is your favorite color?'),
Comment(14, 'What is your quest?'),
Comment(15, 'What is the airspeed velocity of an unladen swallow?'),
]
for comment in comments:
print('{}: {}'.format(comment.id, comment.title))
# or
for comment in comments:
comment = comment._asdict()
print('{}: {}'.format(comment['id'], comment['title']))
Upvotes: 0
Reputation: 504
You can probably use Bunch for this.
Bunch is a dictionary that supports attribute-style access, a la JavaScript
Upvotes: 0
Reputation: 20789
As @Tim Castelijns said, that's not how dicts work.
The behavior you seek can be achieved by having a Comment
class which holds the id
and title
as members.
class Comment
def __init__(self, id, title):
self.id = id
self.title = title
class CommentsHolder:
def __init__(self):
self.comments = [Comment(1,'bla'),
Comment(2,'bla2'),
Comment(3, 'bla3')]
def __iter__(self):
return iter(self.comments)
You can then do:
for comment in CommentsHolder():
print(comment.id)
Furthermore, you can take a look at the Bunch module, which is a dot-accessible dictionary. However if you are using python 3, be aware that it might not work. (at least it didn't for me.)
Upvotes: 5