如何遍历实例对象的数据属性,每次返回两个值?
我需要一次返回两个值,所以我写了:
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 个回答
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 对象都会创建一组默认的余额,这最终会给你带来麻烦。
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 文档 中的解决方案不太一样,因为如果可迭代的对象里有奇数个元素,最后一个元素是不会被返回的。不过我觉得 itertools
例子里的解决办法更好。
5
在itertools的文档中,有一个叫做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
(字典)时,里面的项目不一定是按顺序返回的,所以你最好先进行排序。