Цикл for dict не работает после выполнения списка - PullRequest
2 голосов
/ 09 января 2012

Я пишу код на Python, который должен анализировать файл CSV. Вычислите среднее значение определенной строки, а затем отправьте электронное письмо получателям на основе значений одной строки в файле CSV. Мой код выглядит следующим образом. Я удалил код отправки электронного письма и заменил его оператором печати:

def main():
  #smtp_instance = smtplib.SMTP('localhost')
  ldap_file = open('ldaps.csv','rU')
  ldap_data=csv.DictReader(ldap_file) 
  scores = list(int(d['score']) for d in ldap_data)

  average_score = sum(scores) / len(scores)
  print average_score

  for rows in ldap_data:
    ldap = rows['ldap']
    fullname = rows['fullname']
    firstname = fullname.split(' ')[0]
    location = rows['location']
    score = rows['score']
    if int(score) < average_score:
      score_msg = 'below'
    else:
      score_msg = 'above'

    print 'Hi ' + firstname + '\n'\
          'You got a ' + score + '% on your Final Exam.'\
          'The average score was ' + average_score + '.'\
          'This means that you scored ' + score_msg + ' average.'

if __name__ == '__main__':
  main()

Когда я запускаю это, он печатает значение average_score. Но код никогда не попадает в for..loop. Кажется, что я не могу назвать списочное понимание по поводу диктата, а затем повторить то же самое. Есть идеи, что я делаю не так и как я могу это исправить?

Ответы [ 4 ]

6 голосов
/ 09 января 2012

Объекты чтения, возвращаемые модулем csv, ведут себя как генераторы, их можно повторять только один раз.Если вам нужен реальный список, который вы можете многократно повторять, вы должны создать его явно:

ldap_data = list(csv.DictReader(ldap_file))
1 голос
/ 09 января 2012

Это потому, что ldap_data является объектом чтения, который поддерживает только протокол итератора.Это означает, что вы можете повторить его только один раз, что вы делаете при создании scores списка.

Вы должны либо поместить его в коллекцию, либо, если файл слишком большой, прочитать его еще раз перед циклом.

1 голос
/ 09 января 2012

Эта строка

scores = list(int(d['score']) for d in ldap_data)

потребляет все данные в ldap_data. ldap_data - это итератор, управляемый базовыми данными в файле ldap_file. Когда вы выполняете итерацию по ldap_data, базовый файл ldap_file используется.

То есть ldap_data пусто, когда достигает for-loop.

for rows in ldap_data:

Одним из способов решения этой проблемы является создание ldap_data списка:

ldap_data  = list(csv.DictReader(ldap_file))

Другой способ обойти это - сказать ldap_file снова прочитать с начала:

scores = list(int(d['score']) for d in ldap_data)
...
ldap_file.seek(0)  
...
for rows in ldap_data:
0 голосов
/ 09 января 2012

Какой тип данных ldap?

У меня такое ощущение, что это итератор, а не список, поэтому, если вы выполните итерацию по нему один раз (например, в понимании списка), в следующий раз, когда вы попытаетесь выполнить итерацию по нему, сразу же будет выдан "StopIteration".

Попробуйте скопировать его в список сразу после

ldap_data = csv.DictReader(ldap_file) 
ldap_data = list(ldap_data)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...