Pull to refresh

Comments 10

А зачем писать велосипед? Замена символов на '' стоку с длинной 0 вам не поможет ибо. Привет.мир = Приветмир.
Привет, мир = Приветмир.
Используйте регулярные выражения, для точного поиска слов .


words = re.findall('\w+', text)
return list(Set(words))

Глава "Количество уникальных слов" сделало мне очень грустно. Будто бы нету в питоне такого типа как set. Или даже dict. Нет, мы лучше будем гонять разрастающийся список туда-сюда в цикле внутри цикла.

Хм, честно говоря, как раз-таки первоначально и сделал через словарь, либо set, однако потом подумал, пускай через список, раз статья для начинающих. Хотя, безусловно, реализация словарем или множеством делает это гораздо эстетичнее.
да и к тому же не особо много переписывать придется
def counter():
with open(filename) as file:
text = file.read()

Подаем на вход текст размером в пару сотен гигабайт и наблюдаем как наша программа радостно выжирает всю опреативку и подвешивает ОС.

Если в Linux есть еще надежда на OOM Killer, то винду такое точно убьет.
Вот примерно так можно сделать
from re import findall

def counter(fileName):
  wc = set()
  with open(fileName ,'rt') as f:
    for line from f:
      wc.update(findall(r'\w+', line.lower()))
  return len(wc)
Двоеточий, точек с запятой, кавычек и т.п. в текстах, очевидно. не бывает. А словари (если уж действительно частотный анализ устраивать), множества и \w придумали лентяи.
Изначально у Вас функция counter использовалась для только для подсчёта слов и это было хорошо.

Чтобы функция counter не зависила от компонента реализующего GUI достаточно было:

1. задавать имя файла как аргумент функции counter:
def counter(filename):

2. возвращать полученные значения в виде кортежа:
return (len(words), len(nonrep_words))

Когда Вы добавили в функцию counter часть функционала, связанного с работой GUI — стало хуже. Теперь логика программы привязана к варианту взаимодействия с пользователем.

В целях самообразования рекомендую Вам:
1) всё что касается работы с GUI вынести в отдельную функцию
2) добавить функции для вывода результата в stdout и для вывода в файл
3) с помощью стандартной библиотеки argparse реализовать различные варианты запуска вашей программы

Например, при запуске с параметрами:
--input file_in брать данные из file_in и выводить результат в stdout
--input file_in --output file_out брать данные из file_in и выводить результат в file_out
--gui запускать приложение с графическим интерфейсом

В сочетании с
if __name__ == '__main__':
    ...

п. 1) позволит Вам как запускать данный скрипт на исполнение, так и экспортировать из него отдельные функции, например, counter

п. 3) наглядно покажет преимущество отделения логики от представления.
Так как статья рассчитана на новичков, поделюсь аналогичной программой для командной строки:
import re, argparse
from os import path

parser = argparse.ArgumentParser(description='Count words in text file.')
parser.add_argument('path', action='store', type=str, help='path to a text file')
args = parser.parse_args()

if path.exists(args.path) and path.isfile(args.path):
    with open(args.path, 'r') as f:
        text = f.read()
else:
    exit(f'Path "{args.path}" does not exist or a directory.')

if not text:
    exit('File is empty.')

words = [word.lower() for word in re.split(r'[^\w-]+', text) if word]
print('Words: ', len(words))
print('Unique words: ', len(set(words)))

Так же согласен с товарищами выше, в Питоне есть более интересные инструменты для выполнения данной задачи, чем предложил автор.
Sign up to leave a comment.

Articles