如何迭代实例对象的数据属性,一次返回两个值?

时间:2010-04-13 12:55:41

标签: python iterator

我需要一次返回两个值,所以我有:

class IterableObject(object):
  def __iter__(self):
    for item in self.__dict__:
      return  self.__dict__[item + 1], self.__dict__[item]

所以我可以:

myObj1, myObj2 = IterableObject()

value = myObj1.balance - myObj2.balance

当然没用。我究竟做错了什么?我想我不能在这样的项目上增值。

3 个答案:

答案 0 :(得分:5)

itertools documentation中有一个名为pairwise的示例函数,您可以将其复制到项目中:

def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None)
    return izip(a, b)

使用它像:

for x1, x2 in pairwise(some_iterable):
    # etc..

请注意,当您遍历dict时,项目不一定按顺序返回,因此您应该先排序。

答案 1 :(得分:1)

没有itertools的可能解决方案:

def pairwise(iterable):
    it = iter(iterable)
    try:
        while True:
            yield it.next(), it.next()
    catch StopIteration:
        pass

>>> list(pairwise(range(6))
[(0, 1), (2, 3), (4, 5)]
>>> list(pairwise(range(5))
[(0, 1), (2, 3)]

这与itertools documentation中的解决方案的不同之处在于,如果碰巧包含奇数个元素,则永远不会从迭代中返回最后一项。但我想itertools示例中的解决方案更好。

答案 2 :(得分:1)

对您自己的示例稍作修改可以为您提供所需内容。 您的原始示例显示您不知道迭代字典会为您提供字典的键。 “aproprty_name”+ 1几乎不会给你你想要的东西。

class IterableObject:
  def __iter__(self):
    properties = (i for i in self.__dict__)
    While True:
      a = properties.next()
      try:
        b = properties.next()
      except StopIteration:
        yield (getattr(self,a), ) #for the odd number of properties case
        raise StopIteration
      yield getattr(self, a), getattr(self, b)

这不适用于您提供的示例。你不能盲目地预测任何顺序中的值会使另一个中的值减去有意义。

您可能需要的是一个对象,该对象从您知道为偶数个值的值列表中返回接下来的两个值。您必须在对象中设置该列表。这样,按顺序排列的配对将以相同的顺序传回。

class PairedList:
  def __iter__(self):
    balances = iter(self.balances)
    while True:
      yield balances.next(), balances.next()

>>> b = PairedList()
>>> b.balances = (2000, 151, 1000, 255, 600, 150, 0, 20, 30, 30, 50, 10)
>>> [i for i in b]
[(2000, 151), (1000, 255), (600, 150), (0, 20), (30, 30), (50, 10)]
>>> [(balance-withdrawal, balance, withdrawal) for balance, withdrawal in b]
[(1849, 2000, 151), (745, 1000, 255), (450, 600, 150), (-20, 0, 20), (0, 30, 30), (40, 50, 10)]

您可能希望重新阅读问题和示例并对其进行重新措辞,因为正如所写的那样,您正在创建一个新对象并期望它已经包含您的值。使用我的PairedList类的一个例子就是:

>>> PairedList.balances = b.balances
>>> [(balance-withdrawal, balance, withdrawal) for balance, withdrawal in PairedList()]
[(1849, 2000, 151), (745, 1000, 255), (450, 600, 150), (-20, 0, 20), (0, 30, 30), (40, 50, 10)]

但这几乎肯定不是你想要的。默认情况下,它会限制您只有一组可以迭代的余额。并且会为每个PairedList对象创建一组默认的余额,这些对象最终会在对接中咬你。