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

  • Генераторы словарей

  • Словари со значениями по умолчанию

  • Обход в цикле и копирование коллекций

  • Итераторы, функции и операторы для работы

  • __iter__() , стр. 319 164 Глава 3. Типы коллекций Таблица 3.4. Общие функции и операторы для работы с итерируемыми объектами Синтаксис

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


    Скачать 3.74 Mb.
    НазваниеРуководство издательство СимволПлюс
    Дата10.11.2022
    Размер3.74 Mb.
    Формат файлаpdf
    Имя файлаПрограммирование на Python 3.pdf
    ТипРуководство
    #780382
    страница20 из 74
    1   ...   16   17   18   19   20   21   22   23   ...   74
    160
    Глава 3. Типы коллекций
    Чтобы прояснить, как функционирует метод dict.setdefault(), ниже приводятся два эквивалентных фрагмента программного кода:
    if site not in sites:
    sites[site] = set()
    sites.setdefault(site, set()).add(fname) sites[site].add(fname)
    Для полноты картины ниже приводится остальная часть программы:
    for site in sorted(sites):
    print("{0} is referred to in:".format(site))
    for filename in sorted(sites[site], key=str.lower):
    print(" {0}".format(filename))
    Под каждым вебсайтом выводится с отступом список файлов, в которых встречается ссылка на этот вебсайт.
    Вызов функции sorted() во внешнем цикле for ... in вы
    полняет сортировку ключей словаря – всякий раз, когда словарь используется в контексте, где требуется итери
    руемый объект, используются его ключи. Если необхо
    димо выполнить итерации по элементам (ключ, значе
    ние) или по значениям, можно использовать методы dict.items()
    или dict.values(). Внутренний цикл for ...
    in выполняет итерации по отсортированному списку имен файлов, присутствующих во множестве имен фай
    лов для данного сайта.
    Генераторы словарей
    Генератор словарей
    – это выражение и цикл с необязательным усло
    вием, заключенное в фигурные скобки, очень напоминающее генера
    тор множеств. Подобно генераторам списков и множеств, генераторы словарей поддерживают две формы записи:
    {keyexpression: valueexpression for key, value in iterable}
    {keyexpression: valueexpression for key, value in iterable if condition}
    Ниже показано, как можно использовать генератор словарей для соз
    дания словаря, в котором каждый ключ является именем файла в те
    кущем каталоге, а каждое значение – это размер файла в байтах:
    file_sizes = {name: os.path.getsize(name) for name in os.listdir(".")}
    Функция os.listdir() из модуля os («operating system» –
    операционная система) возвращает список файлов и ка
    талогов в указанном каталоге, но при этом в список ни
    когда не включаются специальные имена каталогов «.»
    или «..». Функция os.path.getsize() возвращает размер заданного файла в байтах. Чтобы отфильтровать катало
    ги и другие элементы списка, не являющиеся файлами,
    можно добавить дополнительное условие:
    Функция
    sorted()
    , стр. 164, 170
    Модули
    os
    и
    os.path
    , стр. 261

    Отображения
    161
    file_sizes = {name: os.path.getsize(name) for name in os.listdir(".")
    if os.path.isfile(name)}
    Функция os.path.isfile() из модуля os.path возвращает True, если ука
    занный путь соответствует файлу, и False – в противном случае, то есть для каталогов, ссылок и тому подобного.
    Генераторы словарей могут также использоваться для создания инвер
    тированных словарей. Например, пусть имеется словарь d, тогда мы можем создать новый словарь, ключами которого будут значения сло
    варя d, а значениями – ключи словаря d:
    inverted_d = {v: k for k, v in d.items()}
    Полученный словарь можно инвертировать обратно и получить перво
    начальный словарь – при условии, что все значения в первоначальном словаре были уникальными, однако инверсия будет терпеть неудачу,
    с возбуждением исключения TypeError, если какоелибо значение ока
    жется не хешируемым.
    Точно так же, как и в случае с генераторами списков и множеств, в ка
    честве итерируемого объекта в генераторах словарей могут использо
    ваться другие генераторы, то есть это могут быть вложенные генерато
    ры любого типа.
    Словари со значениями по умолчанию
    Словари со значениями по умолчанию – это обычные словари, они под
    держивают те же самые методы и операторы, что и обычные словари.
    1
    Единственное, что отличает такие словари от обычных словарей, – это способ обработки отсутствующих ключей, но во всех остальных отно
    шениях они ничем не отличаются друг от друга.
    При обращении к несуществующему («отсутствующему») ключу слова
    ря возбуждается исключение KeyError. Это очень удобно, так как неред
    ко для нас бывает желательно знать об отсутствии ключа, который, со
    гласно нашим предположениям, может присутствовать. Но в некоторых случаях бывает необходимо, чтобы в словаре присутствовали все ключи,
    которые мы используем, даже если это означает, что элемент с задан
    ным ключом добавляется в словарь в момент первого обращения к нему.
    Например, допустим, что имеется словарь d, который не имеет элемен
    та с ключом m, тогда выражение x = d[m] возбудит исключение KeyEr
    ror
    . Если d – это словарь со значениями по умолчанию, созданный со
    ответствующим способом, а элемент с ключом m принадлежит такому словарю, то при обращении к нему будет возвращено соответствующее значение, как и в случае с обычным словарем. Но если в словаре со значениями по умолчанию отсутствует ключ m, то будет создан новый
    1
    Примечание для программистов, использующих объектноориентирован
    ный стиль: defaultdict – это подкласс класса dict.

    162
    Глава 3. Типы коллекций элемент словаря с ключом m и со значением по умолчанию, и будет воз
    вращено значение этого, вновь созданного элемента.
    Ранее мы написали небольшую программу, которая под
    считывала количество вхождений каждого отдельного слова в файлы, имена которых передавались в виде аргу
    ментов командной строки. В этой программе создавался словарь слов, как показано ниже:
    words = {}
    Каждый ключ в словаре words является словом, а значение – целым числом, в котором хранится количество вхождений данного слова во всех файлах. Ниже показано, как увеличивается значение счетчика,
    соответствующего некоторому слову:
    words[word] = words.get(word, 0) + 1
    Мы вынуждены были использовать метод dict.get(), чтобы учесть слу
    чай, когда слово встречается впервые (когда необходимо создать но
    вый элемент со значением счетчика, равным 1), а также случаи, когда слово встречается повторно (когда необходимо прибавить 1 к значе
    нию счетчика для уже существующего слова).
    При создании словаря со значениями по умолчанию мы можем опреде
    лять фабричную функцию. Фабричная функция – это функция, кото
    рая вызывается, чтобы получить объект определенного типа. Все встроенные типы данных языка Python могут использоваться как фаб
    ричные функции, например, тип данных str может вызываться как функция str(), которая при вызове без аргументов возвращает пустой строковый объект. Фабричная функция, передаваемая словарю со зна
    чениями по умолчанию, используется для создания значений по умол
    чанию для отсутствующих ключей.
    Обратите внимание, что имя функции – это ссылка на объект функ
    ции, поэтому, когда функция передается в качестве аргумента, пере
    дается одно только имя функции. Когда вслед за именем функции за
    писываются круглые скобки, они сообщают интерпретатору, что он должен вызвать эту функцию.
    Программа uniquewords2.py на одну строку длиннее, чем исходная программа uniquewords1.py (import collections), а, кроме того, измени
    лись строки создания и обновления словаря. Ниже показано, как соз
    дается словарь со значениями по умолчанию:
    words = collections.defaultdict (int)
    Словарь со значениями по умолчанию words никогда не возбудит ис
    ключение KeyError. Если будет необходимо выполнить выражение x =
    words["xyz"]
    и в словаре будет отсутствовать элемент с ключом "xyz", то при обращении к несуществующему ключу словарь со значениями по умолчанию немедленно создаст новый элемент с ключом "xyz" и значе
    Пример
    unique
    words1.py
    , стр. 155

    Обход в цикле и копирование коллекций
    163
    нием 0 (вызовом функции int()), и это значение будет присвоено пере
    менной x.
    words[word] += 1
    Теперь мы можем отказаться от использования метода dict.get() и про
    сто увеличивать значение элемента. Когда будет обнаружено самое первое вхождение слова, будет создан новый элемент со значением 0
    (к которому тут же будет прибавлено число 1), а при обнаружении ка
    ждого последующего вхождения число 1 будет добавляться к текуще
    му значению.
    Мы закончили полный обзор всех встроенных типов коллекций языка
    Python и пары типов коллекций из стандартной библиотеки. В сле
    дующем разделе мы рассмотрим некоторые проблемы, общие для всех типов коллекций.
    Обход в цикле и копирование коллекций
    После того как будет создана коллекция элементов данных, вполне ес
    тественно возникает желание обойти все элементы, содержащиеся в ней. В первом подразделе этого раздела мы познакомимся с итерато
    рами языка Python, а также с операторами и функциями, применяе
    мыми для работы с итераторами.
    Еще одна часто выполняемая операция – копирование коллекций. Из
    за того, что в языке Python повсеместно используются ссылки на объ
    екты (ради повышения эффективности), существуют некоторые осо
    бенности, связанные с копированием, поэтому во втором подразделе этого раздела мы изучим принципы копирования коллекций и узна
    ем, как добиться именно того, что нам нужно.
    Итераторы, функции и операторы для работы
    с итерируемыми объектами
    Итерируемый
    тип данных – это такой тип, который мо
    жет возвращать свои элементы по одному. Любой объ
    ект, имеющий метод __iter__(), или любая последова
    тельность (то есть объект, имеющий метод __getitem__(),
    принимающий целочисленный аргумент со значением от 0 и выше), является итерируемым и может предостав
    лять итератор. Итератор – это объект, имеющий метод
    __next__()
    , который при каждом вызове возвращает оче
    редной элемент и возбуждает исключение StopIteration после исчерпания всех элементов. В табл. 3.4 перечисле
    ны операторы и функции, которые могут применяться к итерируемым объектам.
    Специальный метод
    __iter__()
    , стр. 319

    164
    Глава 3. Типы коллекций
    Таблица 3.4. Общие функции и операторы для работы
    с итерируемыми объектами
    Синтаксис
    Описание
    s + t
    Возвращает конкатенацию последовательностей s и t s * n
    Возвращает конкатенацию из int n последовательностей s x in i
    Возвращает True, если элемент x присутствует в итерируемом объекте i, обратная проверка выполняется с помощью оператора not in all(i)
    Возвращает True, если все элементы итерируемого объекта i в ло
    гическом контексте оцениваются как значение True any(i)
    Возвращает True, если хотя бы один элемент итерируемого объек
    та i в логическом контексте оценивается как значение True enumerate
    (i,start)
    Обычно используется в циклах for ... in, чтобы получить последо
    вательность кортежей (index, item), где значения индексов начина
    ют отсчитывать от 0 или от значения start; подробности в тексте len(x)
    Возвращает «длину» объекта x. Если x – коллекция, то возвра
    щаемое число представляет количество элементов. Если x – стро
    ка, то возвращаемое число представляет количество символов max(i, key)
    Возвращает наибольший элемент в итерируемом объекте i или элемент с наибольшим значением key(item), если функция key оп
    ределена min(i, key)
    Возвращает наименьший элемент в итерируемом объекте i или элемент с наименьшим значением key(item), если функция key
    определена range
    (start,
    stop,
    step)
    Возвращает целочисленный итератор. С одним аргументом (stop)
    итератор представляет последовательность целых чисел от 0 до stop – 1
    , с двумя аргументами (start, stop) – последовательность целых чисел от start до stop – 1, с тремя аргументами – последо
    вательность целых чисел от start до stop – 1 c шагом step
    reversed(i)
    Возвращает итератор, который будет возвращать элементы ите
    ратора i в обратном порядке sorted
    (i, key,
    reverse)
    Возвращает список элементов итератора i в отсортированном по
    рядке; аргумент key используется для выполнения сортировки
    DSU (Decorate, Sort, Undecorate – декорирование, сортировка,
    обратное декорирование). Если аргумент reverse имеет значение
    True
    , сортировка выполняется в обратном порядке sum
    (i, start)
    Возвращает сумму элементов итерируемого объекта i, плюс ар
    гумент start (значение которого по умолчанию равно 0); объект i не должен содержать строк zip(i1,
    ..., iN)
    Возвращает итератор кортежей, используя итераторы от i1 до iN;
    подробности в тексте

    Обход в цикле и копирование коллекций
    165
    Порядок, в котором возвращаются элементы, зависит от итерируемого объекта. В случае списков и кортежей элементы обычно возвращаются в предопределенном порядке, начиная с первого элемента (находя
    щегося в позиции с индексом 0), но другие итераторы возвращают элементы в произвольном порядке – например, итераторы словарей и множеств.
    Встроенная функция iter() используется двумя совершенно различны
    ми способами. Применяемая к коллекции или к последовательности,
    она возвращает итератор для заданного объекта или возбуждает исклю
    чение TypeError, если объект не является итерируемым. Такой способ часто используется при работе с нестандартными типами коллекций и крайне редко – в других контекстах. Во втором варианте использова
    ния функции iter() ей передается вызываемый объект (функция или метод) и специальное значение. В этом случае полученная функция или метод вызывается на каждой итерации, а значение этой функции, если оно не равно специальному значению, возвращается вызывающей про
    грамме; в противном случае возбуждается исключение StopIteration.
    Когда в программе используется цикл for item in iterable, интерпре
    татор Python вызывает функцию iter(iterable), чтобы получить ите
    ратор. После этого на каждой итерации вызывается метод __next__()
    итератора, чтобы получить очередной элемент, а когда возбуждается исключение StopIteration, оно перехватывается и цикл завершается.
    Другой способ получить очередной элемент итератора состоит в том,
    чтобы вызвать встроенную функцию next(). Ниже приводятся два экви
    валентных фрагмента программного кода (оба они вычисляют произве
    дение элементов списка), в одном из них используется цикл for ... in,
    а во втором явно используется итератор:
    product = 1
    i = iter([1, 2, 4, 8])
    while True:
    try:
    product = 1 product *= next(i)
    for i in [1, 2, 4, 8]: except StopIteration:
    product *= i break print(product) # выведет: 64 print(product) # выведет: 64
    Любой (конечный) итерируемый объект i может быть преобразован в кортеж вызовом функции tuple(i) или в список – вызовом функции list(i)
    К итераторам могут применяться функции all() и any(),
    и они часто используются в функциональном програм
    мировании. Ниже приводится пара примеров, демонст
    рирующих использование функций all(), any(), len(),
    min()
    , max() и sum():
    >>> x = [2, 9, 7, 4, 3]
    >>> all(x), any(x), len(x), min(x), max(x), sum(x)
    Функциональ
    ное програм
    мирование, стр. 397

    166
    Глава 3. Типы коллекций
    (True, True, 5, 4, 9, 13)
    >>> x.append(0)
    >>> all(x), any(x), len(x), min(x), max(x), sum(x)
    (False, True, 6, 4, 9, 13)
    Из всех этих маленьких функций наиболее часто, пожалуй, использу
    ется функция len().
    Функция enumerate() принимает итератор и возвращает объект пере
    числения. Этот объект может рассматриваться как своего рода итера
    тор. На каждой итерации он возвращает кортеж из двух элементов,
    первый из которых – это номер итерации (по умолчанию нумерация начинается с 0), а второй – следующий элемент итератора, который был передан функции enumerate(). Давайте рассмотрим порядок ис
    пользования функции enumerate() в контексте небольшой, но закон
    ченной программы.
    Программа grepword.py принимает в виде аргументов командной стро
    ки слово и одно или более имен файлов. Она выводит имя файла, но
    мер строки и саму строку, содержащую искомое слово.
    1
    Ниже приво
    дится пример сеанса работы с программой:
    grepword.py Dom data/forenames.txt data/forenames.txt:615:Dominykas data/forenames.txt:1435:Dominik data/forenames.txt:1611:Domhnall data/forenames.txt:3314:Dominic
    Файлы с данными data/forenames.txt и data/surnames.txt содержат несортированные списки имен, по одному имени в каждой строке.
    Не считая инструкции импортирования модуля sys, программа зани
    мает всего десять строк:
    if len(sys.argv) < 3:
    print("usage: grepword.py word infile1 [infile2 [... infileN]]")
    sys.exit()
    word = sys.argv[1]
    for filename in sys.argv[2:]:
    for lino, line in enumerate(open(filename), start=1):
    if word in line:
    print("{0}:{1}:{2:.40}".format(filename, lino,
    line.rstrip()))
    Программа начинается с проверки наличия хотя бы двух аргументов командной строки. Если число аргументов меньше двух, программа вы
    водит сообщение с инструкцией о порядке использования и завершает работу. Функция sys.exit() немедленно завершает работу программы,
    1
    В главе 9 будут представлены еще две реализации этой программы – grep
    wordp.py
    и grepwordt.py, которые распределяют работу по нескольким про
    цессам и потокам выполнения.

    Обход в цикле и копирование коллекций
    167
    закрывая любые открытые файлы. Она принимает необязательный ар
    гумент типа int, который передается вызывающей командной оболочке.
    Предполагается, что первым аргументом является сло
    во, которое требуется отыскать, а другие аргументы –
    это имена файлов, в которых требуется произвести по
    иск. Мы преднамеренно вызываем функцию open(), не указывая кодировку символов – пользователь может ис
    пользовать в именах файлов шаблонные символы для выбора группы файлов, каждый из которых может иметь собственную кодировку символов, поэтому в дан
    ном случае мы оставляем за интерпретатором право ис
    пользовать платформозависимую кодировку.
    Функция open() возвращает объект файла, открытого в текстовом ре
    жиме, в котором этот объект может использоваться как итератор, воз
    вращая по одной строке из файла в каждой итерации. Передав итератор функции enumerate(), мы получаем итераторперечисление, который в каждой итерации возвращает номер итерации (в переменной lino,
    «line number» – «номер строки») и строку из файла. Если слово, ука
    занное пользователем, присутствует в строке, программа выводит имя файла, номер строки и первые 40 символов этой строки, из которой удаляются завершающие пробельные символы (такие как \n). Функ
    ция enumerate() принимает необязательный именованный аргумент start
    , который по умолчанию имеет значение 0. Мы передаем в этом аргументе значение 1, так как, в соответствии с общепринятыми согла
    шениями, нумерация строк в текстовых файлах начинается с 1.
    Как правило, на практике используется не итераторперечисление,
    а итератор, возвращающий последовательные целые числа. Это имен
    но то, что делает функция range(). Если нам необходим кортеж или список целых чисел, мы можем преобразовать итератор, возвращае
    мый функцией range(), воспользовавшись соответствующей функцией преобразования, как показано ниже:
    >>> list(range(5)), list(range(9, 14)), tuple(range(10, 11, 5))
    ([0, 1, 2, 3, 4], [9, 10, 11, 12, 13], (10, 5, 0, 5, 10))
    Функция range() обычно используется в двух случаях: для создания списков или кортежей целых чисел и в качестве счетчика в циклах for
    ... in
    . Например, следующие два эквивалентных примера преобразу
    ют значения в списке в положительные числа:
    i = 0
    while i < len(x):
    for i in range(len(x)): x[i] = abs(x[i])
    x[i] = abs(x[i]) i += 1
    В обоих случаях, если предположить, что x – это список значений [11,

    3,

    12, 8,

    1]
    , то после выполнения фрагментов он превратится в спи
    сок [11, 3, 12, 8, 1].
    Врезка «Чте
    ние и запись текстовых файлов», стр. 157

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


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