Как я могу упростить этот код Python (задание из книги)? - PullRequest
0 голосов
/ 20 января 2019

Я изучаю "Питон для всех" книгу, написанную Чарльзом Р. Северансом, и у меня есть вопрос к упражнению2 из главы 7.

Задача состоит в том, чтобы просмотреть файл mbox-short.txt и «Когда вы столкнетесь со строкой, начинающейся с« X-DSPAM-Confidence: », отделите строку, чтобы извлечьчисло с плавающей точкой в ​​строке. Подсчитайте эти строки, а затем вычислите общее значение достоверности спама из этих строк. Когда вы достигнете конца файла, выведите среднюю достоверность спама. "

Вот мой способ выполнения этой задачи:

fname = input('Enter the file name: ') 
try:
    fhand = open(fname) 
except:
    print('File cannot be opened:', fname)
    exit()
count = 0
values = list()
for line in fhand:
    if line.startswith('X-DSPAM-Confidence:'): 
        string = line
        count = count + 1
        colpos = string.find(":")
        portion = string[colpos+1:]
        portion = float(portion)
        values.append(portion)   
print('Average spam confidence:', sum(values)/count)

Я знаю, что этот код работает, потому что я получаю тот же результат, что и в книге, однако я думаю, что этот код может быть проще.Причина, по которой я так думаю, заключается в том, что я использовал список в этом коде (объявил его, а затем сохранил значения в нем).Тем не менее, «Списки» - следующая тема в книге, и когда я решал эту задачу, я ничего не знал о списках, и мне пришлось гуглить по ним.Я решил эту задачу таким образом, потому что это то, что я сделал бы на языке R (с которым я уже хорошо знаком), я бы создал вектор, в котором я буду хранить значения из своей итерации.

Итак, мой вопрос: можно ли упростить этот код?Могу ли я выполнить ту же задачу, не используя список?Если да, как я могу это сделать?

Ответы [ 3 ]

0 голосов
/ 20 января 2019

Вы можете отфильтровать строки файла перед циклом, затем вы можете свернуть другие переменные в одну и получить значения, используя списки. Исходя из этого, у вас есть счет от длины этого списка.

interesting_lines = (line.startswith('X-DSPAM-Confidence:') for line in fhand)
values = [float(line[(line.find(":")+1):]) for line in interesting_lines]
count = len(values)

Могу ли я выполнить ту же задачу без использования списка?

Если выходные данные должны быть средними, да, вы можете накапливать сумму и счет как свои собственные переменные, и вам не нужен список для вызова sum(values) против

Обратите внимание, что open(fname) в любом случае дает вам итеративную коллекцию, и вы перебираете "список строк" в файле.

0 голосов
/ 20 января 2019

Я мог бы изменить объект «значения» на плавающий тип. Переполнение списка не является действительно необходимым в проблеме.

values = 0.0

Тогда в цикле используйте

values += portion 

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

  1. Открыть файл
  2. Проверка на наличие ошибок
  3. Loop Through Lines
  4. Найти определенные строки
  5. Всего до указанных строк
  6. Средняя печать

Если вы можете сделать это в 3 строки кода замечательно, но это не делает то, что происходит в фоновом режиме, обязательно проще. Это также, вероятно, будет выглядеть уродливо.

0 голосов
/ 20 января 2019

Список-списки часто могут заменить циклы for, которые добавляют в список:

fname = input('Enter the file name: ') 
try:
    fhand = open(fname) 
except:
    print('File cannot be opened:', fname)
    exit()

values = [float(l[l.find(":")+1:]) for l in fhand if l.startswith('X-DSPAM-Confidence:')]

print('Average spam confidence:', sum(values)/len(values))

Внутренняя часть - это просто ваш код, объединенный, поэтому, возможно, менее читаемый.

РЕДАКТИРОВАТЬ: Безиспользуя списки, это можно сделать с помощью «redu»:

from functools import reduce
fname = input('Enter the file name: ') 
try:
    fhand = open(fname) 
except:
    print('File cannot be opened:', fname)
    exit()

sum, count = reduce(lambda acc, l: (acc[0] + float(l[l.find(":")+1:]), acc[1]+1) if l.startswith('X-DSPAM-Confidence:') else acc, fhand, (0,0))

print('Average spam confidence:', sum / count)

«Reduce» на других языках часто называют «сворачиванием», и оно в основном позволяет перебирать коллекцию с помощью «аккумулятора».Здесь я повторяю коллекцию с аккумулятором, который является кортежем (sum, count).С каждым элементом мы добавляем к сумме и увеличиваем количество.См. Сокращение документации .

Все это, как говорится, «упрощать» не обязательно означает как можно меньше кода, поэтому я бы придерживался вашего собственного кода, если вам не нравятся этиусловные обозначения.

...