【问题标题】:list of dicts access via class attributes通过类属性访问的字典列表
【发布时间】:2016-10-16 12:12:15
【问题描述】:

我有一个字典列表,我需要访问字典值作为属性。

我的代码:

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)

所以,当我写这样的东西时:

comment_list = Comments()
for comment in comment_list:
    print comment['id']

有效。

但我想将属性用作comment.id 而不是comment['id']

如何实现?

【问题讨论】:

  • 你为什么想要那个?这不是 dicts 的工作方式。它会使阅读您的代码的人感到困惑
  • 你会使用setattr()

标签: python list class dictionary


【解决方案1】:

正如@Tim Castelijns 所说,字典不是这样工作的。

您所寻求的行为可以通过拥有idtitle 作为成员的Comment 类来实现。

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)

你可以这样做:

for comment in CommentsHolder():
    print(comment.id)

此外,您可以查看Bunch module,这是一个点可访问的字典。但是,如果您使用的是 python 3,请注意它可能无法正常工作。 (至少它不适合我。)

【讨论】:

    【解决方案2】:

    您可能可以使用Bunch

    Bunch 是一个支持属性样式访问的字典,类似于 JavaScript

    【讨论】:

      【解决方案3】:

      另一种完整性方法 - 使用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']))
      

      【讨论】:

        【解决方案4】:
        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 使用自 here

        【讨论】:

          【解决方案5】:

          您可以创建字典子类的 cmets 实例,允许正常访问以及点属性样式访问。有多种实现方式,但以下是最简单的一种,即让每个实例都有自己的__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)
          

          请注意,Comment 字典可以创建任何 many ways regular dictionaries can,因此除了上面显示的内容之外,comments 列表中的实例可以像这样创建,它使用关键字来定义它们的内容:

          class Comments(object):
              def __init__(self):
                  self.comments = [Comment(id=1, title='bla'),
                                   Comment(id=2, title='bla2'),
                                   Comment(id=3, title='bla3')]
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-03-03
            • 1970-01-01
            • 2021-01-17
            • 2013-01-19
            • 1970-01-01
            相关资源
            最近更新 更多