Саммерфилд - Программирование на Python 3 (1077331), страница 34
Текст из файла (страница 34)
Ниже приводится основная часть программы: аыеа = () Гог Га1епапе ап ауа.агру(1:]: Гог 1апе (п орел(Г»1апапе) 1 = О пла1е Тгое: а(ге = лопе Отображения 159 1 = 1!па.!!по("Ьттр://, !) тт ! > -т. ! += 1еп("Пттр.//") Гог 1 1п гаппе(1, 1еп( 1!па)): тт пот (11па[1 ]. 1аа1пип() пг 1тпе[1 ] тп ".-' ): а!те = 1!па[1.1'].1о»ег() ЬгеаК !т а1те апа "." тп а!те; ютеа.аетсетаи11(а1те, ает()).аос(11!арапе) =) е1ае: ЬгеаК Программа начинается с создания пустого словаря. Затем выполняются итерации по списку файлов, перечисленных в командной строке, и по строкам в каждом файле.
Нам необходимо учесть тот факт, что в каждой строке может содержаться произвольное число ссылок на веб-сайты, поэтому мы продолжаем вызывать метод атг.(тпо() в цикле, пока поиск не завершится неудачей. Если обнаруживается строка «Ы!рт//», мы увеличиваем значение переменной 1 (начальная позиция в строке) на длину строки «Ы!р // » и затем просматриваем все последующие символы, пока не будет найден символ, недопустимый в именах веб-сайтов. Если обнаружена ссылка на сайт (в качестве простой проверки мы убеждаемся, что она содержит символ точки), мы добавляем ее в словарь.
Мы не можем использовать выражение аттеа[а11е]. аес(тт1епазе), потому что в самый первый раз, когда сайт еще отсутствует в словаре, это выражение будет возбуждать исключение КеуЕггог — т. к. нельзя добавить новое значение к множеству, которое пока отсутствует в словаре. Поэтому мы используем иной подход. Метод Сто!, аетоетао11() возвращает ссылку на элемент словаря с заданным ключом (первый аргумент). Если такой элемент отсутствует, метод создает новый элемент с указанным ключом и устанавливает в качестве значения либо йопе, либо указанное значение по умолчанию (второй аргумент). В данном случае в качестве значения по умолчанию передается результат вызова функции ает(), то есть пустое множество.
Поэтому вызов метода Этот. аетоетао11( ) всегда будет возвращать ссылку на значение, либо существовавшее ранее, либо на вновь созданное. (Безусловно, если указанный ключ не является хешируемым значением, будет возбуждено исключение ТуреЕггог.) В данном примере возвращаемая ссылка всегда будет указывать на множество (пустое множество при первом упоминании каждого конкретного ключа, то есть сайта), после чего мы добавляем имя файла, где встречена ссылка на сайт, ко множеству имен файлов для данного сайта.
Использование множества гарантирует, что даже при наличии в файле нескольких ссылок на один и тот же сайт имя файла будет записано всего один раз. Глава 3. Типы коллекций Чтобы прояснить, как функционирует метод 010!.ве!ое(ао1!(), ниже приводятся два эквивалентных фрагмента программного кода: 1т в!тв пот 1п в1твв; в[сев[в!те] = вет() в1твв[юге].аОО((папе) в1тев ввтаетао11(в!те, вец ) ) , аОО((паза) Для полноты картины ниже приводится остальная часть программы: Гог втте 1п вогтва(в!тев): ргтпт("(О) !в ге(еггва то !п ".Гогзат(в!те)) гог 111епаав 1п вогтво(в!гав[в!те], кау=втг.1онег): ргтпт(" (0)Г.тогаат((1!арапе)) Генераторы словарей Генератор словарей — это выражение и цикл с необязательным усло- вием, заключенное в фигурные скобки, очень напоминающее генера- тор множеств.
Подобно генераторам списков и множеств, генераторы словарей поддерживают две формы записи: (Кауехргевв1оп: »а1оеехргевюоп Гог Кеу, уа1ое 1п ттегав]о) (Кеуехргевв1оп: уа1иеахргевюоп тог Кау, уа1ое !п ттегав]е тт сопш Г]оп! Ниже показано, как можно использовать генератор словарей для соз- дания словаря, в котором каждый ключ является именем файла в те- кущем каталоге, а каждое значение — это размер файла в байтах: 111е в!хев = (павв: ов.ратп.рвтв12е(папе) гог паве 1п ов.11вто1г(".")) Функция ов.1!в!01г() из модуля ов (»орега11пя вувСетп»вЂ” операционная система) возвращает список файлов и каталогов в указанном каталоге, но при этом в список никогда не включаются специальные имена каталогов», » или» .. ».
Функция ов. ратл. Оетв!ге() возвращает размер заданного файла в байтах. Чтобы отфильтровать каталоги и другие элементы списка, не являющиеся файлами, можно добавить дополнительное условие: о Морупи ов и ов. ратЬ, стр. 261 о Под каждым веб-сайтом выводится с отступом список Функция во,тво() файлов, в которых встречается ссылка на этот веб-сайт. стр. 104, 170 Вызов функции бог!еб() во внешнем цикле Гог ... тп выполняет сортировку ключей словаря — всякий раз, когда словарь используется в контексте, где требуется итерируемый объект, используются его ключи. Если необходимо выполнить итерации по элементам (ключ, значение) или по значениям, можно использовать методы 0101.1!езв() или О!ст.уа1оев(). Внутренний цикл (ог !п выполняет итерации по отсортированному списку имен файлов, присутствующих во множестве имен файлов для данного сайта.
161 Отображения гт1е в!зев = (паве: ов.ратп.се!в!те(папе) гсг паве тп св. 1твтс1г(".") тб ов.ратя.твтт1в(паве)) Функция ов. ра1й. 1в(11е() из модуля ов. ратй возвращает Тгие, если указанный путь соответствует файлу, и Еа1ве — в противном случае, то есть для каталогов, ссылок и тому подобного. Генераторы словарей могут также использоваться для создания инвертированных словарей, Например, пусть имеется словарь б, тогда мы можем создать новый словарь, ключами которого будут значения словаря О, а значениями — ключи словаря О: 1п»егтео о = (з. я гог м, ч тп ш 1теев()) Полученный словарь можно инвертировать обратно и получить первоначальный словарь — при условии, что все значения в первоначальном словаре были уникальными, однако инверсия будет терпеть неудачу, с возбуждением исключения ТуреЕггог, если какое-либо значение окажется не хешируемым.
Точно так же, как и в случае с генераторами списков и множеств, в качестве итерируемого объекта в генераторах словарей могут использоваться другие генераторы, то есть это могут быть вложенные генераторы любого типа. Словари со значениями по умолчанию Словари со значениями по умолчанию — это обычные словари, они поддерживают те же самые методы и операторы, что и обычные словари.' Единственное, что отличает такие словари от обычных словарей, — это способ обработки отсутствующих ключей, но во всех остальных отношениях они ничем не отличаются друг от друга. При обращении к несуществующему (» отсутствующему») ключу словаря возбуждается исключение КеуЕггог. Это очень удобно, так как нередко для нас бывает желательно знать об отсутствии ключа, который, согласно нашим предположениям, может присутствовать.
Но в некоторых случаях бывает необходимо, чтобы в словаре присутствовали все ключи, которые мы используем, даже если это означает, что элемент с заданным ключом добавляется в словарь в момент первого обращения к нему. Например, допустим, что имеется словарь О, который не имеет элемента с ключом в, тогда выражение х = б(з] возбудит исключение КеуЕггог. Если о — это словарь со значениями по умолчанию, созданный соответствующим способом, а элемент с ключом а принадлежит такому словарю, то при обращении к нему будет возвращено соответствующее значение, как и в случае с обычным словарем. Но если в словаре со значениями по умолчанию отсутствует ключ а, то будет создан новый Примечание для программистов, использующих объектно-ориентирован- ный стиль: Сетзз!10!с! — зто подкласс класса Зтст.
162 Глаза 3. Типы коллекций элемент словаря с ключом в и со значением по умолчанию, и будет возвращено значение этого, вновь созданного элемента. Ранее мы написали небольшую программу, которая подсчитывала количество вхождений каждого отдельного слова в файлы, имена которых передавались в виде аргументов командной строки, В этой программе создавался словарь слов, как показано ниже: когтев = () Каждый ключ в словаре вогез является словом, а значение — целым числом, в котором хранится количество вхождений данного слова во всех файлах. Ниже показано, как увеличивается значение счетчика, соответствующего некоторому слову: иегов(еегз] = еегзв еег(еегз, 0) е 1 Мы вынуждены были использовать метод З ест, цег(), чтобы учесть случай, когда слово встречается впервые (когда необходимо создать новый элемент со значением счетчика, равным 1), а также случаи, когда слово встречается повторно (когда необходимо прибавить 1 к значению счетчика для уже существующего слова).
При создании словаря со значениями по умолчанию мы можем определять фабричную функцию. Фабричная функция — это функция, которая вызывается, чтобы получить объект определенного типа. Все встроенные типы данных языка РуСЬоп могут использоваться как фабричные функции, например, тип данных ввг может вызываться как функция в( г(), которая при вызове без аргументов возвращает пустой строковый объект. Фабричная функция, передаваемая словарю со значениями по умолчанию, используется для создания значений по умолчанию для отсутствующих ключей. Обратите внимание, что имя функции — это ссылка на объект функции, поэтому, когда функция передается в качестве аргумента, передается одно только имя функции.