-1

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()は実行されません。ジェネレーターのポイントは、データベース内のすべての行のリストを返すのではなく、1 つずつ返す必要があるということです。次に、それらのアイテムにアクセス/印刷したいと思いました。このコードを修正するにはどうすればよいですか?

4

3 に答える 3

5

cursor.fetchall() を実行している場合は、SQL サーバーから取得できるすべての結果を Python のメモリにコピーしていることを意味します。したがって、このコンテキストでは、ジェネレーターは何も提供しません。

代わりにcursor.fetchmany()またはcursor.fetchone()を使用した場合、一度に「いくつかの」または「1つの」結果しか処理しないため、Python側でのメモリ消費が唯一の利点になります。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

ジェネレーターは、非同期で処理を行う場合に非常に役立ちます。基本的に、ジェネレーターがまだ準備できていない場合は、スキップして他の処理を実行できます。

于 2013-08-06T01:57:00.660 に答える
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: # ...ます (コードが読みやすくなり、元に戻すようなことをした場合に壊れにくくなるためです)。リストを返す通常のジェネレータ関数への変換)。

于 2013-08-06T01:59:57.163 に答える
0

私の最初の答えは正しくなく、他の人が既に最善の解決策を示しているので、代替案と潜在的な使用例を述べます。一度に 2 つの項目をジェネレーターで反復処理する必要がある場合、またはその他の独自の方法で、この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)
于 2013-08-06T01:53:40.963 に答える