我在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()
个语句都没有执行。生成器的要点是,它不是返回数据库中所有行的列表,而是应该逐个返回它。然后我想访问/打印这些项目。我该怎么做才能修复此代码?
答案 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)