简体   繁体   English

使用生成器函数python

[英]Using generator functions python

I was practicing using generator functions in python, so I defined a functions as follows: 我正在练习在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

However, when I run this code, all I see as an output is generator object at ... I am trying to print the contents that are found in the database. 但是,当我运行此代码时,我看到的只是输出generator object at ...处的generator object at ...我试图打印数据库中找到的内容。 Also, none of the print statements in MySQL_product() are executed. 另外, MySQL_product()中的所有print语句都不执行。 The point of the generator is that instead of return a list of all of the rows in the database, it should return it one by one. 生成器的要点是,与其返回数据库中所有行的列表,不如返回一个列表。 Then I wanted to access/print those items. 然后,我想访问/打印这些项目。 What can I do to fix this code? 我该怎么做才能修复此代码?

If you're doing a cursor.fetchall(), that means you're copying every result available from the SQL server into python's memory. 如果要执行cursor.fetchall(),则意味着您要将SQL Server可用的每个结果复制到python的内存中。 So in this context - a generator affords you nothing. 因此,在这种情况下-生成器无法为您提供任何服务。

If you instead used cursor.fetchmany() or cursor.fetchone(), the only benefit you would see is memory consumption on Python's side since you would only be processing 'some' or 'one' result at a time. 如果改为使用cursor.fetchmany()或cursor.fetchone(),则您看到的唯一好处就是Python方面的内存消耗,因为一次只能处理“一些”或“一个”结果。 On the SQL side, the server would still have that result set cached (burning up valuable resources on the SQL server) 在SQL方面,服务器仍将缓存该结果集(消耗SQL服务器上的宝贵资源)

But, ultimately - if you did process results in chunks - since you'd be in a loop of: 但是,最终-如果您确实按块处理结果-因为您将处于以下循环中:

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

Having a generator would provide you no real advantage since you would have to block while you get more results from mysql. 拥有生成器不会给您带来任何真正的优势,因为当您从mysql中获得更多结果时必须阻塞。

However, to answer your question 但是,回答您的问题

What you want to do to make the code you have work is: 要使您的代码有效,您要做的是:

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

generators are really useful when you're doing things asynchronously - basically if a generator isn't ready yet - you just skip over it and let other things work. 当您异步执行操作时,生成器确实很有用-基本上,如果生成器尚未准备好,您只需跳过它,然后让其他功能工作即可。

Yes, that's how a generator behaves - it always returns an iterator which you can then use with eg the for statement. 是的,这就是生成器的行为-它总是返回一个迭代器,然后您可以将其与for语句一起使用。 You probably want to change your main() function to something like this: 您可能想要将main()函数更改为以下形式:

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

It's also possible to get the next result yielded by an iterator with the next() function, but in general you should prefer to iterate directly with for item in iterator: # ... (because your code will be easier to read, and less fragile in the event that you do something like switch back from a generator function to a regular one that returns a list). 也可以使用next()函数获得由迭代器产生的下一个结果,但是通常,您应该更喜欢直接for item in iterator: # ... (因为您的代码将更易于阅读,而且花费更少如果您执行类似的操作(从生成器功能切换回返回列表的常规功能),则该功能将变得脆弱。

My first answer was incorrect and others have already given the best solution, so I'll state the alternative and a potential use case. 我的第一个答案是错误的,其他人已经给出了最佳解决方案,因此,我将说明替代方案和潜在的用例。 If you need to iterate over a generator two items at a time, or in any other custom way, the next method can be useful. 如果您需要一次在生成器上迭代两个项目,或者以任何其他自定义方式进行迭代,那么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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM