2013-08-06 2 views
0

Я практиковал с помощью функции генератора в питоне, поэтому я определил функции следующим образом:Использование функции генератора питон

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

Если вы делаете cursor.fetchall(), это означает, что вы копируете каждый результат, имеющийся на сервере SQL в память питона. Поэтому в этом контексте генератор ничего не дает вам.

Если вы использовали курсор.fetchmany() или cursor.fetchone(), единственное преимущество, которое вы увидите, это потребление памяти на стороне 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 

генераторы действительно полезны, когда вы делаете вещи асинхронно - в основном, если генератор еще не готов - вы просто пропустите его и позволите другим вещам работать.

+0

Так что я меняю 'fetchall()' в 'MySQL_product()' на 'fetchone()' когда я выполняю ваш 'main'? –

+0

Получение одного результата за один раз будет довольно медленным, оптимальный размер зависит от того, как настроен ваш сервер mysql. Попробуйте 256 в качестве отправной точки. – synthesizerpatel

+0

Я не уверен, следую ли вы тому, что вы имеете в виду, можете ли вы взглянуть на отредактированный вопрос? Если я понимаю, что вы говорите, генератор не может эффективно использоваться в этой проблеме? –

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) 
+1

print students.next() напечатал бы только один результат. Вы должны перебирать генератор. – synthesizerpatel

+0

Да, я собирался отредактировать свой ответ, потому что понял это. –

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: # ... (т.к. ваш код будет легче читать и менее хрупким в том случае, если вы сделаете что-то вроде переключения с генераторной функции на обычную, которая возвращает список).

+0

Как насчет функции 'MySQL_product()', я могу изменить 'fetchall()'? –

+0

@MaxKim не знаю; Я не заглянул в вашу функцию 'MySQL_product()', но @synthesizerpatel, похоже, вас охватил. –

Смежные вопросы