Главная страница
Навигация по странице:

  • Рис. 3.5.

  • Синтаксис Описание

  • Чтение и запись текстовых файлов

  • Программирование на Python 3. Руководство издательство СимволПлюс


    Скачать 3.74 Mb.
    НазваниеРуководство издательство СимволПлюс
    Дата10.11.2022
    Размер3.74 Mb.
    Формат файлаpdf
    Имя файлаПрограммирование на Python 3.pdf
    ТипРуководство
    #780382
    страница19 из 74
    1   ...   15   16   17   18   19   20   21   22   ...   74
    152
    Глава 3. Типы коллекций как они являются неупорядоченными коллекциями, к ним не приме
    нимо понятие индекса и не применима операция извлечения среза.
    Тип данных dict может вызываться как функция dict() –
    без аргументов она возвращает пустой словарь; если в качестве аргумента передается отображение, возвраща
    ется словарь, основанный на этом отображении: напри
    мер, с аргументом типа dict возвращается поверхностная копия словаря. Существует возможность передавать в качестве аргумента последовательности, если каждый элемент последовательности в свою очередь является по
    следовательностью из двух объектов, первый из которых используется в качестве ключа, а второй – в качестве зна
    чения. Как вариант, для создания словарей, в которых ключи являются допустимыми идентификаторами язы
    ка Python, можно использовать именованные аргумен
    ты; тогда имена аргументов будут играть роль ключей, а значения аргументов – роль значений ключей. Кроме то
    го, словари могут создаваться с помощью фигурных ско
    бок – пустые скобки {} создадут пустой словарь. Непус
    тые фигурные скобки должны содержать один или более элементов, разделенных запятыми, каждый из которых состоит из ключа, символа двоеточия и значения. Еще один способ создания словарей заключается в использо
    вании генераторов словарей – эта тема будет рассматри
    ваться ниже, в соответствующем подразделе.
    Ниже приводятся несколько способов создания словарей – все они соз
    дают один и тот же словарь:
    d1 = dict({"id": 1948, "name": "Washer", "size": 3})
    d2 = dict(id=1948, name="Washer", size=3)
    d3 = dict([("id", 1948), ("name", "Washer"), ("size", 3)])
    d4 = dict(zip(("id", "name", "size"), (1948, "Washer", 3)))
    d5 = {"id": 1948, "name": "Washer", "size": 3}
    Словарь d1 создается с помощью литерала словаря. Сло
    варь d2 создается с помощью именованных аргументов.
    Словари d3 и d4 создаются из последовательностей, а сло
    варь d5 создается из литерала словаря. Встроенная функ
    ция zip(), использованная при создании словаря d4, воз
    вращает список кортежей, первый из которых содержит первые элементы всех итерируемых аргументов функ
    ции zip(), второй – вторые элементы и т. д. Синтаксис,
    основанный на применении именованных аргументов
    (использованный при создании словаря d2), обычно явля
    ется наиболее компактным и удобным, но при этом клю
    чами могут быть только допустимые идентификаторы.
    Поверхно
    стное и глубокое копирование, стр. 173
    Именованные аргументы, стр. 206
    Генераторы словарей, стр. 160
    Функция
    zip()
    , стр. 169

    Отображения
    153
    На рис. 3.5 демонстрируется словарь, созданный следующим фрагмен
    том программного кода:
    d = {"root": 18, "blue": [75, "R", 2], 21: "venus", 14: None,
    "mars": "rover", (4, 11): 18, 0: 45}
    Ключи словарей являются уникальными, поэтому если в словарь до
    бавляется пара «ключзначение» с ключом, который уже присутству
    ет в словаре, в результате происходит замена значения существующе
    го ключа новым значением. Для доступа к отдельным элементам ис
    пользуются квадратные скобки: например, выражение d["root"] вер
    нет 18, выражение d[21] вернет строку "venus", а выражение d[91]
    применительно к словарю, изображенному на рис. 3.5, возбудит ис
    ключение KeyError.
    Квадратные скобки могут также использоваться для добавления и уда
    ления элементов словаря. Чтобы добавить новый элемент, использует
    ся оператор =, например, d["X"] = 59. Для удаления элементов исполь
    зуется инструкция del, например, инструкция del d["mars"] удалит из словаря элемент с ключом "mars" или возбудит исключение KeyError,
    если элемент с указанным ключом отсутствует в словаре. Кроме того,
    элементы могут удаляться (и возвращаться вызывающей программе)
    методом dict.pop().
    Словари поддерживают встроенную функцию len() и для ключей под
    держивают возможность быстрой проверки на вхождение с помощью операторов in и not in. В табл. 3.3 перечислены все методы словарей.
    Так как словари содержат пары «ключзначение», у нас может воз
    никнуть потребность обойти в цикле элементы словаря (ключ, значе
    ние) по значениям или по ключам. Например, ниже приводятся два эквивалентных способа обхода пар «ключзначение»:
    for item in d.items(): for key, value in d.items():
    print(item[0], item[1]) print(key, value)
    14
    None
    'blue'
    [75, 'R', 2]
    (4, 11)
    18 21
    'venus'
    'root'
    18
    'mars'
    'rover'
    0 45
    Рис. 3.5. Словарь – это неупорядоченная коллекция элементов
    (ключ, значение) с уникальными ключами

    154
    Глава 3. Типы коллекций
    Таблица 3.3. Методы словарей
    Обход значений в словаре выполняется похожим способом:
    for value in d.values():
    print(value)
    Для обхода ключей в словаре можно использовать метод dict.keys()
    или просто интерпретировать словарь как итерируемый объект и вы
    полнить итерации по его ключам, как показано в следующих двух фрагментах:
    Синтаксис
    Описание
    d.clear()
    Удаляет все элементы из словаря d d.copy()
    Возвращает поверхностную копию словаря d d.fromkeys(
    s, v)
    Возвращает словарь типа dict, ключами которого являются элементы последовательности s, а значениями либо None, либо
    v
    , если аргумент v определен d.get(k)
    Возвращает значение ключа k или None, если ключ k отсутствует в словаре d.get(k, v)
    Возвращает значение ключа k или v, если ключ k отсутствует в словаре d.items()
    Возвращает представление a
    всех пар (ключ, значение) в словаре d a
    Представления словарей можно трактовать и использовать как итерируе
    мые объекты. Они обсуждаются ниже, в этом же разделе.
    d.keys()
    Возвращает представление а
    всех ключей словаря d d.pop(k)
    Возвращает значение ключа k и удаляет из словаря элемент с ключом k или возбуждает исключение KeyError, если ключ k отсутствует в словаре d.pop(k, v)
    Возвращает значение ключа k и удаляет из словаря элемент с ключом k или возвращает значение v, если ключ k отсутствует в словаре d.popitem()
    Возвращает и удаляет произвольную пару (ключ, значение) из словаря d или возбуждает исключение KeyError, если словарь d пуст d.setdefault(
    k, v)
    То же, что и dict.get() за исключением того, что, если ключ k в словаре отсутствует, в словарь вставляется новый элемент с ключом k и со значением None или v, если аргумент v задан d.update(a)
    Добавляет в словарь d пары (ключ, значение) из a, которые от
    сутствуют в словаре d, а для каждого ключа, который уже при
    сутствует в словаре d, выполняется замена соответствующим значением из a; a может быть словарем, итерируемым объектом с парами (ключ, значение) или именованными аргументами d.values()
    Возвращает представление а
    всех значений в словаре d
    Поверхностное и глубокое копи
    рование, стр. 173

    Отображения
    155
    for key in d: for key in d.keys():
    print(key) print(key)
    Если необходимо изменить значения в словаре, то можно выполнить обход ключей словаря в цикле и изменить значения, используя опера
    тор квадратных скобок. Например, ниже показано, как можно было бы увеличить все значения в словаре d, если предполагать, что все зна
    чения являются числами:
    for key in d:
    d[key] += 1
    Методы dict.items(), dict.keys() и dict.values() возвращают представ
    ления словарей
    . Представление словаря – это в действительности ите
    рируемый объект, доступный только для чтения и хранящий элемен
    ты, ключи или значения словаря в зависимости от того, какое пред
    ставление было запрошено.
    Вообще, мы легко можем интерпретировать представления как итери
    руемые объекты. Однако между представлениями и обычными итери
    руемыми объектами есть два различия. Одно из них заключается в том,
    что если словарь, для которого было получено представление, изменя
    ется, то представление будет отражать эти изменения. Другое отличие состоит в том, что представления ключей и элементов поддерживают некоторые операции, свойственные множествам. Допустим, у нас име
    ются представление словаря v и множество или представление словаря x
    ; для этой пары поддерживаются следующие операции:
    v & x # Пересечение v | x # Объединение v  x # Разность v ^ x # Строгая дизъюнкция
    Для проверки наличия некоторого определенного ключа в словаре мож
    но использовать оператор проверки на вхождение in, например, x in d.
    Чтобы выяснить, какие ключи из заданного множества присутствуют в словаре, можно использовать оператор пересечения. Например:
    d = {}.fromkeys ("ABCD", 3) # d == {'A': 3, 'B': 3, 'C': 3, 'D': 3}
    s = set("ACX") # s == {'A', 'C', 'X'}
    matches = d.keys() & s # matches == {'A', 'C'}
    Обратите внимание, что в комментариях в этом фрагменте программ
    ного кода мы указали ключи в алфавитном порядке – это сделано лишь для простоты восприятия, поскольку словари и множества явля
    ются неупорядоченными коллекциями.
    Словари часто используются для хранения счетчиков уникальных эле
    ментов. Один такой пример – подсчет числа вхождений каждого от
    дельного слова в файле. Ниже приводится программный код закон
    ченной программы (uniqwords1.py)), которая выводит в алфавитном

    156
    Глава 3. Типы коллекций порядке список слов с количеством вхождений каждого из них во всех файлах, перечисленных в командной строке:
    import string import sys words = {}
    strip = string.whitespace + string.punctuation + string.digits + "\"'"
    for filename in sys.argv[1:]:
    for line in open(filename):
    for word in line.lower().split():
    word = word.strip(strip)
    if len(word) > 2:
    words[word] = words.get (word, 0) + 1
    for word in sorted(words):
    print("'{0}' occurs {1} times".format(word, words[word]))
    Программа начинается с создания пустого словаря с именем words, за
    тем путем конкатенации некоторых полезных строк, объявленных в модуле string, создается строка, содержащая все символы, которые мы будем игнорировать. Мы выполняем итерации по всем именам файлов, полученным в виде аргументов командной строки, и по всем строкам в каждом файле. Описание функции open() смотрите во врезке
    «Чтение и запись текстовых файлов» (стр. 157). Мы не указываем ко
    дировку символов (потому что не знаем, какой она будет в каждом файле) и позволяем интерпретатору открывать каждый файл, исполь
    зуя по умолчанию локальную кодировку. После приведения всех сим
    волов строки к нижнему регистру она разбивается на слова, после это
    го с обоих концов каждого слова удаляются нежелательные символы.
    Если в получившемся слове осталось хотя бы три символа, мы выпол
    няем обновление словаря.
    Мы не можем использовать синтаксис words[word] += 1, потому что в самый первый раз, когда слово word еще отсутствует в словаре, это выражение будет возбуждать исключение KeyError – мы же не можем увеличивать значение элемента, отсутствующего в словаре. Поэтому мы используем иной подход. Мы вызываем метод dict.get() со значе
    нием по умолчанию 0. Если слово уже присутствует в словаре, метод dict.get()
    вернет существующее значение и это значение, увеличенное на 1, будет записано как новое значение элемента. Если слово отсутст
    вует в словаре, метод dict.get() вернет значение по умолчанию 0 и это значение, увеличенное на 1 (то есть 1), будет записано как значение нового элемента, ключом которого является строка word. Чтобы пояс
    нить ситуацию, ниже приводятся два фрагмента программного кода,
    выполняющего одно и то же, хотя код, использующий метод dict.get()
    , имеет более высокую эффективность:
    if word not in words:
    words[word] = 0
    words[word] = words.get(word, 0) + 1 words[word] += 1

    Отображения
    157
    В следующем подразделе мы познакомимся со словарями, имеющими значения по умолчанию, и рассмотрим альтернативное решение.
    После того, как все встретившиеся слова будут накоплены в словаре,
    выполняются итерации по его ключам (по словам) в алфавитном по
    рядке и выводятся слова и число раз, которое они встречаются.
    Использование метода dict.get() позволяет легко обновлять значения в словаре, возвращая значения, если это отдельные элементы данных,
    такие как числа или строки. Но как быть, если каждое значение само по себе является коллекцией? Чтобы продемонстрировать, как обраба
    тывать такие значения, ниже приводится программа, которая читает
    Чтение и запись текстовых файлов
    Файлы открываются с помощью встроенной функ
    ции open(), которая возвращает «объект файла»
    (типа io.TextIOWrapper для текстовых файлов).
    Функция open() принимает один обязательный ар
    гумент – имя файла, которое может включать путь к файлу, и до шести необязательных аргументов,
    два из которых коротко описываются здесь. Вто
    рой аргумент определяет режим работы с файлом,
    то есть он указывает, будет ли файл интерпретиро
    ваться как текстовый или как двоичный, и для вы
    полнения каких действий будет открыт файл – для чтения, для записи, для дополнения в конец или комбинации этих действий.
    Для работы с текстовыми файлами Python исполь
    зует кодировку символов, зависящую от платфор
    мы. Поэтому, возможно, лучше будет указывать кодировку с помощью аргумента encoding функции open()
    , то есть обычный синтаксис, используемый для открытия файлов, имеет следующий вид:
    fin = open(filename, encoding="utf8") # для чтения текста fout = open(filename, "w", encoding="utf8") # для записи текста
    Поскольку по умолчанию функция open() использует режим
    «для чтения», и для указания кодировки используется имено
    ванный аргумент encoding, а не позиционный, то при открытии файла для чтения можно опустить другие необязательные пози
    ционные аргументы. Аналогично, при открытии файла для за
    писи мы можем указывать только те аргументы, которые дейст
    вительно необходимы. (Вопросы передачи аргументов подробно рассматриваются в главе 4.)
    Глава 7, рабо
    та с файлами, стр. 334
    Kодировки символов, стр. 112

    158
    Глава 3. Типы коллекций содержимое файлов HTML, имена которых указываются в командной строке, и выводит список различных вебсайтов, ссылки на которые присутствуют в файлах, и список файлов, в которых эти ссылки встре
    чаются, ниже каждого вебсайта. По своей структуре программа
    (external_sites.py) очень похожа на программу подсчета числа вхожде
    ний отдельных слов, которую мы только что рассмотрели. Ниже при
    водится основная часть программы:
    sites = {}
    for filename in sys.argv[1:]:
    for line in open(filename):
    i = 0
    while True:
    site = None
    Как только файл будет открыт для чтения в текстовом режиме,
    можно будет прочитать его целиком в одну строку, используя метод объекта файла read(), или в список строк, используя метод объекта файла readlines(). Типичный прием построчного чтения содержимого файла основан на интерпретации объекта файла как итератора:
    for line in open(filename, encoding="utf8"):
    process(line)
    Этот прием работает, потому что объект файла допускает выпол
    нение итераций по нему, как по последовательности, каждый элемент которой представляет собой строку, содержащую от
    дельную строку из файла. Строки, которые в этом случае полу
    чает программа, содержат символы перевода строки \n.
    Если в качестве режима указать «w», файл будет открыт в режи
    ме «записи текста». Запись в файл может производиться с помо
    щью метода объекта файла write(), который в качестве аргумен
    та принимает единственную строку. Каждая записываемая стро
    ка уже должна содержать символ перевода строки \n. При вы
    полнении чтения и записи Python автоматически преобразует символы \n в последовательность символов завершения строки,
    характерную для той или иной платформы.
    После окончания работы с объектом файла можно вызвать его метод close() – это приведет к выталкиванию буферов вывода на диск. В небольших программах на языке Python обычно не при
    нято беспокоиться о вызове функции close(), поскольку Python делает это автоматически, когда объект файла выходит из теку
    щей области видимости. Если возникают какиелибо проблемы,
    объект тут же сообщает о них возбуждением исключений.

    Отображения
    159
    i = line.find("http://", i)
    if i > 1:
    i += len("http://")
    for j in range(i, len(line)):
    if not (line[j].isalnum() or line[j] in "."):
    site = line[i:j].lower()
    break if site and "." in site:
    sites.setdefault(site, set()).add(filename)
    i = j else:
    break
    Программа начинается с создания пустого словаря. Затем выполняются итерации по списку файлов, перечисленных в командной строке, и по строкам в каждом файле. Нам необходимо учесть тот факт, что в каж
    дой строке может содержаться произвольное число ссылок на вебсай
    ты, поэтому мы продолжаем вызывать метод str.find() в цикле, пока поиск не завершится неудачей. Если обнаруживается строка «http://»,
    мы увеличиваем значение переменной i (начальная позиция в строке)
    на длину строки «http://» и затем просматриваем все последующие сим
    волы, пока не будет найден символ, недопустимый в именах вебсайтов.
    Если обнаружена ссылка на сайт (в качестве простой проверки мы убе
    ждаемся, что она содержит символ точки), мы добавляем ее в словарь.
    Мы не можем использовать выражение sites[site].add(filename), пото
    му что в самый первый раз, когда сайт еще отсутствует в словаре, это выражение будет возбуждать исключение KeyError – т. к. нельзя доба
    вить новое значение к множеству, которое пока отсутствует в словаре.
    Поэтому мы используем иной подход. Метод dict.setdefault() возвра
    щает ссылку на элемент словаря с заданным ключом (первый аргу
    мент). Если такой элемент отсутствует, метод создает новый элемент с указанным ключом и устанавливает в качестве значения либо None,
    либо указанное значение по умолчанию (второй аргумент). В данном случае в качестве значения по умолчанию передается результат вызо
    ва функции set(), то есть пустое множество. Поэтому вызов метода dict.setdefault()
    всегда будет возвращать ссылку на значение, либо су
    ществовавшее ранее, либо на вновь созданное. (Безусловно, если ука
    занный ключ не является хешируемым значением, будет возбуждено исключение TypeError.)
    В данном примере возвращаемая ссылка всегда будет указывать на множество (пустое множество при первом упоминании каждого кон
    кретного ключа, то есть сайта), после чего мы добавляем имя файла,
    где встречена ссылка на сайт, ко множеству имен файлов для данного сайта. Использование множества гарантирует, что даже при наличии в файле нескольких ссылок на один и тот же сайт имя файла будет за
    писано всего один раз.

    1   ...   15   16   17   18   19   20   21   22   ...   74


    написать администратору сайта