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

  • Рис. 3.4.

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

  • Генераторы множеств

  • Тип frozenset

  • Отображения

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


    Скачать 3.74 Mb.
    НазваниеРуководство издательство СимволПлюс
    Дата10.11.2022
    Размер3.74 Mb.
    Формат файлаpdf
    Имя файлаПрограммирование на Python 3.pdf
    ТипРуководство
    #780382
    страница18 из 74
    1   ...   14   15   16   17   18   19   20   21   ...   74
    144
    Глава 3. Типы коллекций codes = []
    for sex in "MF": # мужская (Male), женская (Female)
    for size in "SMLX": # маленький, средний, большой, очень большой if sex == "F" and size == "X":
    continue for color in "BGW": # черный (Black), серый (Gray), белый (White)
    codes.append(sex + size + color)
    Этот фрагмент воспроизводит список, содержащий 21 элемент –
    ['MSB', 'MSG', ..., 'FLW']
    . Тот же самый список можно создать парой строк, если воспользоваться генераторами списков:
    codes = [s + z + c for s in "MF" for z in "SMLX" for c in "BGW"
    if not (s == "F" and z == "X")]
    Здесь каждый элемент списка воспроизводится выражением s + z + c.
    Кроме того, в генераторе списков несколько иначе построена логика обхода нежелательной комбинации пол/размер – проверка выполня
    ется в самом внутреннем цикле, тогда как в версии с циклами for ...
    in эта проверка выполняется в среднем цикле. Любой генератор спи
    сков можно переписать, используя один или более циклов for ... in.
    Если сгенерированный список получается очень боль
    шим, то, возможно, более эффективным было бы созда
    вать очередные элементы списка по мере необходимо
    сти, вместо того чтобы создавать сразу весь список. Эту задачу можно решить с помощью выраженийгенерато
    ров, которые будут обсуждаться в главе 8.
    Множества
    Тип set – это разновидность коллекций, которая поддерживает опера
    тор проверки на вхождение in, функцию len() и относится к разряду итерируемых объектов. Кроме того, множества предоставляют метод set.isdisjoint()
    и поддерживают операторы сравнения и битовые опе
    раторы (которые в контексте множеств используются для получения объединения, пересечения и т. д.). В языке Python имеется два встро
    енных типа множеств: изменяемый тип set и неизменяемый frozenset.
    При переборе элементов множества элементы могут следовать в произ
    вольном порядке.
    В состав множеств могут включаться только хешируемые объекты. Хе
    шируемые объекты – это объекты, имеющие специальный метод
    __hash__()
    , на протяжении всего жизненного цикла объекта всегда воз
    вращающий одно и то же значение, которые могут участвовать в опе
    рациях сравнения на равенство посредством специального метода
    __eq__()
    . (Специальные методы – это методы, имена которых начина
    ются и оканчиваются двумя символами подчеркивания; они описыва
    ются в главе 6.)
    Выражения
    генераторы, стр. 397

    Множества
    145
    Все встроенные неизменяемые типы данных, такие как float, frozen
    set
    , int, str и tuple, являются хешируемыми объектами и могут добав
    ляться во множества. Встроенные изменяемые типы данных, такие как dict, list и set, не являются хешируемыми объектами, так как значение хеша в каждом конкретном случае зависит от содержащихся в объекте элементов, поэтому они не могут добавляться в множества.
    Множества могут сравниваться между собой с использованием стан
    дартных операторов сравнения (<, <=, ==, !=, >=, >). Обратите внимание:
    операторы == и != имеют обычный смысл, и сравнение выполняется пу
    тем поэлементного сравнения (или рекурсивно при наличии таких вложенных элементов, как кортежи и фиксированные множества
    (frozenset)), но остальные операторы сравнения выполняют сравнение подмножеств и надмножеств, как вскоре будет показано.
    Тип set
    Тип set – это неупорядоченная коллекция из нуля или более ссылок на объекты, указывающих на хешируемые объекты. Множества относят
    ся к категории изменяемых типов, поэтому легко можно добавлять и удалять их элементы, но, так как они являются неупорядоченными коллекциями, к ним не применимо понятие индекса и не применима операция извлечения среза. На рис. 3.3 иллюстрируется множество,
    созданное следующим фрагментом программного кода:
    S = {7, "veil", 0, 29, ("x", 11), "sun", frozenset({8, 4, 7}), 913}
    Тип данных set может вызываться как функция set() –
    без аргументов она возвращает пустое множество; с аргу
    ментом типа set возвращает поверхностную копию аргу
    мента; в случае, если аргумент имеет другой тип, выпол
    няется попытка преобразовать его в объект типа set. Эта функция принимает не более одного аргумента. Кроме то
    го, непустые множества могут создаваться без использо
    вания функции set(), а пустые множества могут созда
    ваться только с помощью функции set() – их нельзя соз
    дать с помощью пары пустых скобок.
    1
    Множество, со
    стоящее из одного или более элементов, может быть создано с помощью последовательности элементов, разде
    ленных запятыми, заключенной в фигурные скобки.
    Другой способ создания множеств заключается в исполь
    зовании генераторов множеств – эта тема будет рассмат
    риваться ниже в соответствующем подразделе. Множе
    ства всегда содержат уникальные элементы – добавле
    ние повторяющихся элементов возможно, но не имеет
    1
    Пустые фигурные скобки {} используются для создания пустого словаря,
    как будет показано в следующем разделе.
    Поверхно
    стное и глубокое копирование, стр. 173
    Генераторы множеств, стр. 149

    146
    Глава 3. Типы коллекций смысла. Например, следующие три множества являются эквивалент
    ными: set("apple"), set("aple") и {'e', 'p', 'a', 'l'}. Благодаря этой их особенности множества часто используются для устранения повто
    ряющихся значений. Например, если предположить, что x – это спи
    сок строк, то после выполнения инструкции x = list(set(x)) в списке останутся только уникальные строки, причем располагаться они мо
    гут в произвольном порядке.
    ('x', 11)
    'sun'
    29
    'veil'
    7 913 0
    frozenset({8, 4, 7})
    Рис. 3.3. Множество – это неупорядоченная коллекция
    уникальных элементов




    \


    set("pecan") | set("pie") == {'p', 'e', 'c', 'a', 'n', 'i'} # Объединение set("pecan") & set("pie") == {'p', 'e'}
    # Пересечение set("pecan")  set("pie") == {'c', 'a', 'n'}
    # Разность p
    e c
    a n
    p i
    e c
    a n
    i p
    e c
    a n
    p i
    e c
    a n
    p e
    c a
    n p
    i e
    p e
    p e
    c a
    n p
    i e
    p e
    c a
    n i
    set("pecan") ^ set("pie") == {'c', 'a', 'n', 'i'}
    # Строгая дизъюнкция
    (исключающее ИЛИ)
    Рис. 3.4. Стандартные операторы множеств

    Множества
    147
    Множества поддерживают встроенную функцию len() и быструю про
    верку на вхождение с помощью операторов in и not in. Они также пре
    доставляют типичный набор операторов, как показано на рис. 3.4.
    Полный перечень методов и операторов, применимых к множествам,
    приводится в табл. 3.2. Все методы семейства «update» (set.update(),
    set.intersection_update()
    и т. д.) могут принимать в качестве аргумен
    та любые итерируемые объекты, но эквивалентные им комбинирован
    ные операторы присваивания (|=, &= и т. д.) требуют, чтобы оба операн
    да были множествами.
    Таблица 3.2. Методы и операторы множеств
    Синтаксис
    Описание
    s.add(x)
    Добавляет элементы x во множество s, если они от
    сутствуют в s s.clear()
    Удаляет все элементы из множества s s.copy()
    Возвращает поверхностную ко
    пию множества s a
    a
    Этот метод и соответствующий ему оператор (если таковой имеется) могут также применять к фиксированным множествам.
    s.difference(t) s  t
    Возвращает новое множество, включающее элемен
    ты множества s, которые отсутствуют в множестве t а
    s.difference_update(t)
    s = t
    Удаляет из множества s все элементы, присутствую
    щие в множестве t s.discard(x)
    Удаляет элемент x из множества s, если он присутст
    вует в множестве s; смотрите также метод set.remove()
    s.intersection(t) s & t
    Возвращает новое множество, включающее элементы,
    присутствующие одновременно в множествах s и t а
    s.intersection_update(t) s &= t
    Оставляет во множестве s пересечение множеств s и t s.isdisjoint(t)
    Возвращает True, если множества s и t не имеют об
    щих элементов а
    s.issubset(t) s <= t
    Возвращает True, если множество s эквивалентно мно
    жеству t или является его подмножеством; чтобы про
    верить, является ли множество s только подмножест
    вом множества t, следует использовать проверку s < t а
    s.issuperset(t) s >= t
    Возвращает True, если множество s эквивалентно мно
    жеству t или является его надмножеством; чтобы про
    верить, является ли множество s только надмножест
    вом множества t, следует использовать проверку s > t а
    Поверхностное и глубокое копи
    рование, стр. 173

    148
    Глава 3. Типы коллекций
    Таблица 3.2 (продолжение)
    Типичный случай использования множеств – когда необходимо орга
    низовать быструю проверку на вхождение. Например, нам может по
    требоваться выводить на экран инструкцию о порядке использования программы, когда пользователь вводит аргументы «

    h» или «
    ––
    help»:
    if len(sys.argv) == 1 or sys.argv[1] in {"h", "help"}:
    Другой типичный случай использования множеств – когда необходи
    мо избежать обработки повторяющихся элементов данных. Например,
    предположим, что имеется итерируемый объект (такой как список),
    содержащий IPадреса, извлеченные из файлов журнала вебсервера,
    и необходимо выполнить некоторые действия, причем не более одного раза для каждого отдельного IPадреса. Допустим, что IPадреса со
    храняются в хешируемом и итерируемом объекте ips и что для каждо
    го адреса должна вызываться функция process_ip(), которая уже опре
    делена. Тогда следующие фрагменты программного кода сделают то,
    что нам требуется, хотя и немного поразному:
    seen = set()
    for ip in ips:
    if ip not in seen:
    seen.add(ip) for ip in set(ips):
    process_ip(ip) process_ip(ip)
    Синтаксис
    Описание
    s.pop()
    Возвращает и удаляет случайный элемент множества s
    или возбуждает исключение KeyError, если s – это пустое множество s.remove(x)
    Удаляет элемент x из множества s или возбуждает ис
    ключение KeyError, если элемент x отсутствует в мно
    жестве s; смотрите также метод set.discard()
    s.symmetric_
    difference(t) s ^ t
    Возвращает новое множество, включающее все эле
    менты, присутствующие в множествах s и t, за ис
    ключением элементов, присутствующих в обоих мно
    жествах одновременно а
    s.symmetric_
    difference_update(t) s ^= t
    Возвращает в множестве s результат строгой дизъ
    юнкции множеств s и t а
    s.union(t) s | t
    Возвращает новое множество, включающее все эле
    менты множества s и все элементы множества t, от
    сутствующие в множестве s а
    s.update(t) s |= t
    Добавляет во множество s все элементы множества t,
    отсутствующие в множестве s

    Множества
    149
    Во фрагменте слева, если очередной IPадрес еще не обрабатывался, он добавляется во множество seen и обрабатывается, в противном случае адрес пропускается. В фрагменте справа мы изначально имеем дело только с уникальными IPадресами. Различие между этими фрагмен
    тами заключается, вопервых, в том, что в левом фрагменте создается множество seen, необходимость в котором отсутствует в правом фраг
    менте, и, вовторых, в левом фрагменте IPадреса обрабатываются в порядке, в каком они присутствуют в объекте ips, тогда как в правом фрагменте они обрабатываются в произвольном порядке.
    Фрагмент справа выглядит проще, но, если порядок обработки эле
    ментов объекта ips имеет значение, придется использовать фрагмент слева или изменить первую строку во фрагменте справа – например,
    так: for ip in sorted(set(ips)):, если этого будет достаточно, чтобы по
    лучить желаемый порядок следования. Теоретически фрагмент справа может оказаться более медленным при большом количестве элементов в объекте ips, поскольку в нем множество создается целиком, а не с оп
    ределенным шагом.
    Множества также могут использоваться для удаления требуемых эле
    ментов. Например, если представить, что у нас имеется список имен файлов и нам необходимо исключить из него файлы с инструкциями по сборке (возможно, по той простой причине, что они генерируются автоматически, а не создаются вручную), мы могли бы использовать следующий прием:
    filenames = set(filenames)
    for makefile in {"MAKEFILE", "Makefile", "makefile"}:
    filenames.discard(makefile)
    Этот фрагмент удалит все makefile, присутствующие в списке, имена которых следуют стандарту использования заглавных символов. Этот фрагмент ничего не будет делать, если в списке отсутствуют искомые файлы. То же самое может быть реализовано в одной строке программ
    ного кода при помощи оператора получения разности множеств (

    ):
    filenames = set(filenames)  {"MAKEFILE", "Makefile", "makefile"}
    Кроме того, мы могли бы удалить элементы с помощью метода set.re
    move()
    , хотя этот метод возбуждает исключение KeyError, если удаляе
    мый элемент отсутствует во множестве.
    Генераторы множеств
    В дополнение к возможности создавать множества с помощью функ
    ции set() или литералов, существует возможность создавать множест
    ва с помощью генераторов множеств. Генератор множества – это вы
    ражение и цикл с необязательным условием, заключенные в фигур
    ные скобки. Подобно генераторам списков, генераторы множеств под
    держивают две формы записи:

    150
    Глава 3. Типы коллекций
    {expression for item in iterable}
    {expression for item in iterable if condition}
    Мы могли бы использовать генераторы множеств для фильтрации не
    желательных элементов (когда порядок следования элементов не име
    ет значения), как показано ниже:
    html = {x for x in files if x.lower().endswith((".htm", ".html"))}
    Если предположить, что files – это список имен файлов, то данный ге
    нератор множества создает множество html, в котором хранятся только имена файлов с расширениями .htm и .html, независимо от регистра символов.
    Как и в случае с генераторами списков, в генераторах множеств ис
    пользуются итерируемые объеты, которые в свою очередь могут быть генераторами множеств (или генераторами любого другого типа), что позволяет создавать весьма замысловатые генераторы множеств.
    Тип frozenset
    Фиксированное множество (frozenset) – это множество,
    которое после создания невозможно изменить. Хотя при этом мы, конечно, можем повторно связать переменную,
    которая ссылалась на фиксированное множество, с чем
    то другим. Фиксированные множества могут создавать
    ся только в результате обращения к имени типа frozenset как к функции. При вызове frozenset() без аргументов возвращается пустое фиксированное множество; с аргу
    ментом типа frozenset возвращается поверхностная ко
    пия аргумента; если аргумент имеет другой тип, выпол
    няется попытка преобразовать его в объект типа frozen
    set
    . Эта функция принимает не более одного аргумента.
    Поскольку фиксированные множества относятся к категории неизме
    няемых объектов, они поддерживают только те методы и операторы,
    которые воспроизводят результат, не оказывая воздействия на фикси
    рованное множество или на множества, к которым они применяются.
    В табл. 3.2 (на стр. 147) перечислены все методы множеств из которых фиксированными множествами поддерживаются: frozenset.copy(),
    frozenset.difference()
    (

    ), frozenset.intersection() (&), frozenset.isdis
    joint()
    , frozenset.issubset() (<= и < для выявления подмножеств), fro
    zenset.issuperset()
    (>= и > для выявления надмножеств), frozen
    set.union()
    (|) и frozenset.symmetric_difference() (^), – то есть все те, что помечены в таблице знаком сноски a
    Если двухместный оператор применяется ко множеству и фиксиро
    ванному множеству, тип результата будет совпадать с типом операнда,
    стоящего слева от оператора. То есть если предположить, что f – это фиксированное множество, а s – это обычное множество, то выраже
    ние f & s вернет объект типа frozenset, а выражение s & f – объект ти
    Поверхно
    стное и глубокое копирование, стр. 173

    Отображения
    151
    па set. В случае операторов == и != порядок операндов не имеет значе
    ния, и выражение f == s вернет True, только если оба множества содер
    жат одни и те же элементы.
    Другое следствие неизменности фиксированных множеств заключает
    ся в том, что они соответствуют критерию хеширования, предъявляе
    мому к элементам множеств, и потому множества и фиксированные множества могут содержать другие фиксированные множества.
    В следующем разделе, а также в упражнениях в конце главы мы встре
    тим множество примеров использования множеств.
    Отображения
    Отображениями называются типы данных, поддерживающие опера
    тор проверки на вхождение (in), функцию len() и возможность обхода элементов в цикле. Отображения – это коллекции пар элементов
    «ключзначение», которые предоставляют методы доступа к элемен
    там и их ключам и значениям. При выполнении итераций порядок следования элементов отображений может быть произвольным. В язы
    ке Python имеется два типа отображений: встроенный тип dict и тип collections.defaultdict
    , определяемый в стандартной библиотеке. Мы будем использовать термин словарь для ссылки на любой из этих ти
    пов, когда различия между ними не будут иметь никакого значения.
    В качестве ключей словарей могут использоваться толь
    ко хешируемые объекты, поэтому в качестве ключей словаря такие неизменяемые типы, как float, frozenset,
    int
    , str и tuple, использовать допускается, а изменяемые типы, такие как dict, list и set, – нет. С другой стороны,
    каждому ключу соответствует некоторое значение, кото
    рое может быть ссылкой на объект любого типа, вклю
    чая числа, строки, списки, множества, словари, функ
    ции и т. д.
    Словари могут сравниваться с помощью стандартных операторов срав
    нения (<, <=, ==, !=, >=, >), при этом сравнивание производится поэле
    ментно (и рекурсивно, при наличии вложенных элементов, таких как кортежи или словари в словарях). Пожалуй, единственными операто
    рами сравнения, применение которых к словарям имеет смысл, явля
    ются операторы == и !=.
    Словари
    Тип dict – это неупорядоченная коллекция из нуля или более пар
    «ключзначение», в которых в качестве ключей могут использоваться ссылки на хешируемые объекты, а в качестве значений – ссылки на объекты любого типа. Словари относятся к категории изменяемых ти
    пов, поэтому легко можно добавлять и удалять их элементы, но так
    Хешируемые объекты, стр. 145

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


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