我试图通过帮助函数将一系列生成器生成到另一个生成器。我想我试图在RxPy中模仿flat_map()
。有没有办法实现这个目标?我得到一个打印发电机的输出,而不是发电机产生的项目。
class User(object):
def __init__(self, id, name):
self.id = id
self.name = name
def __str__(self):
return "{0}-{1}".format(self.id, self.name)
users = [
User(0,"Hero"),
User(1,"Dunn"),
User(2,"Sue"),
User(3,"Chi"),
User(4,"Thor"),
User(5,"Clive"),
User(6,"Hicks"),
User(7,"Devin"),
User(8,"Kate"),
User(9,"Klein"),
]
friendships = [
(0,1),
(0,2),
(1,2),
(1,3),
(2,3),
(3,4),
(4,5),
(5,6),
(5,7),
(6,8),
(7,8),
(8,9)
]
def user_for_id(user_id):
for user in users:
if user.id == user_id:
yield user
def friends_of(user):
for friendship in friendships:
if friendship[0] == user.id or friendship[1] == user.id:
for other_user_id in friendship:
if other_user_id != user.id:
yield user_for_id(other_user_id)
for friend in friends_of(users[3]):
print(friend)
输出:
<generator object user_for_id at 0x7f2d33ee48e0>
<generator object user_for_id at 0x7f2d33ee4990>
<generator object user_for_id at 0x7f2d33ee4938>
答案 0 :(得分:2)
你的链接生成器在一起,只迭代其中一个。如果你想得到真正的朋友,你需要迭代朋友,即使它是一个单一的价值。生成器不是迭代器。因为您的friends_of
函数返回一个生成器表达式,您需要迭代它或将其传递给next
。
>>> for friend in friends_of(users[3]):
... for obj in friend:
... print(obj.name)
...
Dunn
Sue
Thor
您可以通过将生成器传递给next()
并打印生成的name属性来绕过第二个循环。我应该注意,这段代码与我之前提到的代码不同,因为这只会查看第二个生成器表达式返回的第一个值。
>>> for friend in friends_of(users[3]):
... print(next(friend).name)
...
Dunn
Sue
Thor
如果您在理解发电机方面遇到困难,我强烈建议您查看david beazley网站上发布的材料。
http://dabeaz.com/generators/index.html - 系统程序员的生成器技巧 http://dabeaz.com/generators-uk/index.html - 系统程序员v2的生成器技巧 http://dabeaz.com/finalgenerator/index.html - 发电机最后的边界
他的视频和幻灯片将让您更好地了解生成器如何在python中工作。
正如其他人解释的那样,在Python 3中你可以使用“yield from”:
def friends_of(user):
for friendship in friendships:
if friendship[0] == user.id or friendship[1] == user.id:
for other_user_id in friendship:
if other_user_id != user.id:
yield from user_for_id(other_user_id)
for friend in friends_of(users[3]):
print(friend.name)
上一段代码的深层嵌套是一个不好的迹象。它应该被重写,以便更具可读性。