Kirill Shatalaev
Kirill Shatalaev

Reputation: 53

list of dicts access via class attributes

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

Answers (5)

martineau
martineau

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

Gábor Fekete
Gábor Fekete

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

Wayne Werner
Wayne Werner

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

user1337
user1337

Reputation: 504

You can probably use Bunch for this.

Bunch is a dictionary that supports attribute-style access, a la JavaScript

Upvotes: 0

DJanssens
DJanssens

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

Related Questions