【问题标题】:Implicit Iteration through Python dictionary elements通过 Python 字典元素进行隐式迭代
【发布时间】:2016-07-27 11:04:16
【问题描述】:

我想弄清楚是否有一种隐式的方式来遍历列表元素。示例:使用列表someList = ['a','b','c'],当print(someList) 进行隐式 迭代时,您无需编写for 循环来迭代列表打印元素。

我有以下(简化的)python 代码:

class foo:
    def __init__(self):
        self.x=None
        self.y=None
        self.z=None

    def set(self, x, y , z):
        self.x = x
        self.y = y
        self.z = z

    def get(self):
        return {'x':self.x, 'y':self.y, 'z':self.z}


class bar:
    def __init__(self):
        self.foos=[]
    def add(self, foo):
        self.foos.append(foo)
    def get(self):
        return {'foos':self.foos}

使用

初始化
f = foo()
f.set(1,2,3)

g = foo()
g.set(4,5,6)


h = bar()
h.add(f)
h.add(g)

然后调用

print(f.get())
print(g.get())
print(h.get())

这给了

{'z': 3, 'x': 1, 'y': 2}
{'z': 6, 'x': 4, 'y': 5}
{'foos': [<__main__.foo object at 0x0000000003541748>, <__main__.foo object at 0x000000000358C630>]}

我最终想要做的是返回类似 JSON 的结构或嵌套字典,以便 foo.get() 方法的返回包含在对 bar.get() 的调用中。

我意识到该数组不包含实际的 foo 对象(仅对它们的引用)。

我考虑过使用 迭代器,就像在 http://anandology.com/python-practice-book/iterators.html 中解释的那样。该示例的问题在于,要迭代的项目必须在数据结构中定义(即foo)。将迭代器包含在 bar 类中的问题在于 foos 列表可能不是唯一要迭代的集合:我本可以添加集合 foos2 (但不是为了简单起见)

我考虑了Access nested dictionary items via a list of keys? 的解决方案,但pprint 给了我类似于我自己的代码的东西。我也不确定reduce 函数的使用是否适用于我的情况。

我还考虑过在print 函数上进行运算符重载,但我不想得到一个字符串,只是一个易于显示和导航的数据结构。

有没有简单的方法正确的方法来做到这一点?我是否使用了正确的数据结构(即我应该使用嵌套列表以外的东西)?

我还是 Python 新手,所以请温柔一点。

【问题讨论】:

  • 您这样做仅仅是为了打印吗?还是您真的想将这些数据类型编组为可序列化的格式以保存在某处?

标签: python arrays json list dictionary


【解决方案1】:

如果你想在没有显式循环的情况下实现功能,你可以使用 map:

class bar:
    def __init__(self):
        self.foos = []

    def add(self, foo):
        self.foos.append(foo)

    def get(self):
        return {'foos': list(map(foo.get, self.foos))}

【讨论】:

    【解决方案2】:

    如果您需要使用像列表这样的 foo 对象,我能给您的最好办法是让 foo 可迭代,这可以很容易地做到这一点:

    class foo(object):
        def __iter__(self):
            for item in [self.x, self.y, self.z]:
                yield item
    

    这将允许你说类似list(foo)

    当您需要将可迭代对象转换为 JSON 时。您还可以定义需要迭代哪些项目(及其顺序)来代替 [self.x, self.y, self.z]

    【讨论】:

      【解决方案3】:

      这会在 bar.get() 的返回值中返回 foo.get() 的结果。这是你要求的吗?

      class bar:
          ...
          def get(self):
              return {'foos':[foo.get() for foo in self.foos]}
      

      分解return 语句,

      return (            # you know what this keyword does
          {               # create a dict
              'foos':     # with a key of "foos",
              [           # and a value that is a list
                          # (in this case, built from a list comprehension)
                  x.get() # each element is the result of calling .get()
                  for x in self.foos  # on each element of the "foos" list
              ]           # end of list comprehension
          }               # end of dict
      )                   # end of return expression
      

      因此,return 语句返回一个 dict,其中只有一个键值对。关键是文字字符串"foos"。该值是一个列表,由对self.foos 列表的每个成员调用.get() 的结果组成。 (我更改了循环变量的名称并添加了括号以减少混乱。)

      结果如下:

      {'x': 1, 'z': 3, 'y': 2}
      {'x': 4, 'z': 6, 'y': 5}
      {'foos': [{'x': 1, 'z': 3, 'y': 2}, {'x': 4, 'z': 6, 'y': 5}]}
      

      bar.get() 的完全等效实现可以使用显式for 循环,如下所示。我只使用列表推导,因为我发现该代码更易于阅读。如果您发现以下内容更容易,请改用它。

      def get(self):
          result = []
          for x in self.foos:
              result.append(x.get())
          return result
      

      【讨论】:

      • 简单来说这是在做什么?我知道这是一个列表理解,但不明白它是如何工作的
      • @Rob:是的!这正是我想要做的。谢谢你。我想这不是 implicit vs explicit 迭代的问题,而是 inline vs. non-inline 迭代。那就是我不想编写显式方法(或任何超出get 方法的return 语句的方法)来迭代foos 集合。)
      • @WoodMath - 我不确定您所说的“内联”和“非内联”迭代是什么意思。如果您指的是 for 循环(如 for x in foos: ...),请继续关注。接下来我会添加那个。
      • @Rob - 我所说的内联迭代是声明return {'foos':[foo.get() for foo in self.foos]}。通常我已经完成 for 循环 for x in coll: x.get()], but return {'foos':[for foo in self.foos: foo.get()]}` is not valid python。它是这些语言特定的细微差别之一,这就是我发表原始帖子的原因,因为我需要改变您对常见编程任务的看法。再次感谢。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-08-08
      • 2016-09-29
      • 1970-01-01
      • 2018-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多