使用生成器函数python

时间:2013-08-06 01:44:28

标签: python generator

我在python中练习使用生成器函数,所以我定义了如下函数:

def MySQL_product():
   #Establish connection to database
   try:
       connection = msql.connect(host = 'localhost', user = 'max', passwd = 'password', db = 'schools')
   except:
       pass

   #Iterate through each product and insert them in database
   with connection:
       cursor = connection.cursor()
       cursor.execute("SELECT name, age, gender, school
                    WHERE GroupId = 'student' AND Exchange = 'foreign'")
       for product in cursor.fetchall():
           yield product

def main():
    for column in range (0, number_of_schools):
        for product in MySQL_product():
            print product

但是,当我运行此代码时,我看到的所有输出都是generator object at ...我正在尝试打印数据库中找到的内容。此外,print中的MySQL_product()个语句都没有执行。生成器的要点是,它不是返回数据库中所有行的列表,而是应该逐个返回它。然后我想访问/打印这些项目。我该怎么做才能修复此代码?

3 个答案:

答案 0 :(得分:3)

如果你正在做一个cursor.fetchall(),那意味着你要将SQL服务器提供的每个结果复制到python的内存中。所以在这种情况下 - 发电机什么都不提供。

如果您改为使用cursor.fetchmany()或cursor.fetchone(),那么您将看到的唯一好处是Python端的内存消耗,因为您一次只能处理“some”或“one”结果。在SQL端,服务器仍然会缓存该结果集(在SQL服务器上烧掉宝贵的资源)

但是,最终 - 如果您确实处理了块中的结果 - 因为您处于以下循环中:

while there_are_more_results:
    results = cursor.fetchmany(10)
    for result in results:
        do_something(result)

拥有一个生成器将无法为您提供真正的优势,因为当您从mysql获得更多结果时,您将不得不阻止。

然而,要回答你的问题

您想要做的工作是:

def main():
    for column in range (0, number_of_schools):
        for student in MySQL_product():
            print student
当你异步做事时,

生成器非常有用 - 基本上如果生成器尚未就绪 - 你只需跳过它并让其他东西工作。

答案 1 :(得分:2)

是的,这就是生成器的行为方式 - 它总是返回一个迭代器,然后你可以使用它来实例化它。 for声明。您可能希望将main()函数更改为以下内容:

def main():
    for column in range (0, number_of_schools):
        for student in MySQL_product():
            print student

也可以使用next()函数获得迭代器产生的下一个结果,但一般情况下,您应该更喜欢直接使用for item in iterator: # ...进行迭代(因为您的代码更容易阅读,并且如果您执行诸如从生成器函数切换回返回列表的常规函数​​之类的操作,则不那么脆弱。

答案 2 :(得分:0)

我的第一个答案是不正确的,其他人已经给出了最佳解决方案,因此我将说明替代方案和潜在用例。如果您需要一次迭代生成器两个项目,或者以任何其他自定义方式迭代,next方法可能很有用。

def gen():
    for i in range(20):
        yield i

for i in gen():
    print "Center", str(i).center(10)

a = gen()    
for i in range(10):
    left = str(a.next()).ljust(10)
    right = str(a.next()).rjust(10)