Python - 我的发电机出了什么问题?

时间:2016-10-29 01:26:18

标签: python generator

我试图通过帮助函数将一系列生成器生成到另一个生成器。我想我试图在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>

1 个答案:

答案 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)

上一段代码的深层嵌套是一个不好的迹象。它应该被重写,以便更具可读性。