在while循环中调用.fetchone()
时,编写以下生成器函数是否有优势?如果是这样,那个优势会是什么?
感谢。
def testf2():
db = connectToMysqlDB(None)
sql_statement = " ".join([
"select d.* ",
"from dr_snapshot d ",
"order by d.PremiseID asc, d.last_read asc; "])
sel_cur = db.cursor()
rc = sel_cur.execute(sql_statement)
loop_ok = True
while loop_ok:
meter_row = sel_cur.fetchone()
if meter_row:
yield meter_row
else:
loop_ok = False
yield None
for read_val in testf2():
print(read_val)
#Perform something useful other than print.
('610159000', 6, datetime.datetime(2012, 7, 25, 23, 0), 431900L, 80598726L)
('610160000', 6, datetime.datetime(2012, 7, 25, 23, 0), 101200L, 80581200L)
None
答案 0 :(得分:4)
不。在功能上它们是相同的,但如果你想重用代码,将它包装在生成器中是有好处的。例如,您可以添加代码以在完成读取生成器块后关闭连接/光标。我建议您将其添加到上面的代码中,以便关闭游标。
def testf2():
try:
db = connectToMysqlDB(None)
sql_statement = " ".join([
"select d.* ",
"from dr_snapshot d ",
"order by d.PremiseID asc, d.last_read asc; "])
sel_cur = db.cursor()
rc = sel_cur.execute(sql_statement)
loop_ok = True
while loop_ok:
meter_row = sel_cur.fetchone()
if meter_row:
yield meter_row
else:
loop_ok = False
except ProgrammingError:
print "Tried to read a cursor after it was already closed"
finally:
sel_cur.close()
这样可以更容易重用,因为您只需要在一个地方获得连接管理。
答案 1 :(得分:3)
看起来我是对的,mySQL游标 可迭代(https://stackoverflow.com/a/1808414/138772)。所以你可以这样做而不是你的while循环(但我喜欢把数据库访问代码放在生成器函数中的想法,所以保持这个):
for meter_row in sel_cur:
yield meter_row
另请注意,您可能不希望最终yield None
; StopIteration
异常用于指示迭代器输出的耗尽,并且for
循环用作停止循环的标志,因此通过包含yield None
最终得到None
输出结束时没有实际收益。
答案 2 :(得分:0)
使用生成器可以更灵活地在现有代码中使用结果。例如,您可以将其直接传递给csv.writer
writerows
函数。