Саммерфилд - Программирование на Python 3 (1077331), страница 31
Текст из файла (страница 31)
Это эквивалентно вложению циклов гог ... !и. Например, если бы нам потребовалось сгенерировать список всех возможных кодов одежды для разных полов, разных размеров и расцветок, но исключая одежду для полных женщин, нужды и чаянья которых индустрия моды нередко игнорирует, мы могли бы использовать вложенные циклы гог ... !и, как показано ниже: 144 Глава 3. Типы коллекций сопев = [) тсг ВЕХ 1п "МЕ; Ф Гог в1те тп "ЗМьХ": Ф 11 вех == "Е" апб в(ае сопт1пое Гог со1ог тп "ВВИ": я сосев.аррепс(вех т мужская (Ма!е), женская (Ееша1е) иаленький, средний, большой, очень большой черный (В1аси), серый (Огау), белый (Митте) вые + со1ог) Этот фрагмент воспроизводит список, содержащий 21 элемент— ['МВВ', 'МВВ', ..., 'ЕьИ'). Тот же самый список можно создать парой строк, если воспользоваться генераторами списков: соеев = [в ш г е с Гог в ю "МЕ" Гог а тп "БМ[Х" Гог с тп "ВВИ" тг пот (в == "е" апо т == "х")) ЗДЕСЬ КажДЫйЭЛЕМЕНтСПИСКаВОСПРОИЗВОДИтСЯ ВЫРажЕНИЕМ В т 7 + С.
Кроме того, в генераторе списков несколько иначе построена логика обхода нежелательной комбинации пол/размер — проверка выполня- ется в самом внутреннем цикле, тогда как в версии с циклами тог тп эта проверка выполняется в среднем цикле. Любой генератор спи- сков можно переписать, используя один или более циклов (ог ... 1п. Если сгенерированный список получается очень большим, то, возможно, более эффективным было бы создавать очередные элементы списка по мере необходимости, вместо того чтобы создавать сразу весь список.
Эту задачу можно решить с помощью выражений-генераторов, которые будут обсуждаться в главе 8. а Выражениягенераторы, стр. 397 Множества Тип вет — это разновидность коллекций, которая поддерживает оператор проверки на вхождение [п, функцию 1еп() и относится к разряду итерируемых объектов. Кроме того, множества предоставляют метод ве[.1вбтв)о(пт() и поддерживают операторы сравнения и битовые операторы (которые в контексте множеств используются для получения объединения, пересечения и т. д.). В языке РубЬоп имеется два встроенных типа множеств: изменяемый тип ве1 и неизменяемый Е гохепвет. При переборе элементов множества элементы могут следовать в произвольном порядке.
В состав множеств могут включаться только хешируемые объекты. Хешируемые объекты — это объекты, имеющие специальный метод Паап (), на протяжении всего жизненного цикла объекта всегда возвращающий одно и то же значение, которые могут участвовать в операциях сравнения на равенство посредством специального метода ео (). (Специальные методы — это методы, имена которых начинаются и оканчиваются двумя символами подчеркивания; они описываются в главе 6.) Множества Все встроенные неизменяемые типы данных, такие как (1оат, Ггогепвет, тпт, вт г И тоР1е, являются хешируемыми объектами и могут добавляться во множества. Встроенные изменяемые типы данных, такие как т)тот, 1191 и вес, не являются хешируемыми объектами, так как значение хеша в каждом конкретном случае зависит от содержащихся в объекте элементов, поэтому они не могут добавляться в множества.
Множества могут сравниваться между собой с использованием стандартных операторов сравнения («, =, ==,! =, )=, )). Обратите внимание: операторы == и! = имеют обычный смысл, и сравнение выполняется путем поэлементного сравнения (или рекурсивно при наличии таких вложенных элементов„как кортежи и фиксированные множества (Г гогепввт)), но остальные операторы сравнения выполняют сравнение подмножеств и надмножеств, как вскоре будет показано. ТИП 5Еа Тип вес — зто неупорядоченная коллекция из нуля или более ссылок на объекты, указывающих на хешируемые объекты. Множества относятся к категории изменяемых типов, поэтому легко можно добавлять и удалять их элементы, но, так как они являются неупорядоченными коллекциями, к ним не применимо понятие индекса и не применима операция извлечения среза.
На рис. 3.3 иллюстрируется множество, созданное следующим фрагментом программного кода: Б = (7, ГМЕ '.", О, -29, ("х", 11), "вип", Ггааепэет((Я, 4, т)), 919) Тип данных эет может вызываться как функция эвт()— без аргументов она возвращает пустое множество; с аргументом типа вес возвращает поверхностную копию аргумента; в случае, если аргумент имеет другой тип, выполняется попытка преобразовать его в объект типа вет. Эта функция принимает не более одного аргумента. Кроме того, непустые множества могут создаваться без использования функции ввт(), а пустые множества могут создаваться только с помощью функции вес() — их нельзя создать с помощью пары пустых скобок.' Множество, состоящее из одного или более элементов, может быть создано с помощью последовательности элементов, разделенных запятыми, заключенной в фигурные скобки.
Другой способ создания множеств заключается в использовании генераторов множеств — зта тема будет рассматриваться ниже в соответствующем подразделе. Множества всегда содержат уникальные элементы — добавление повторяющихся элементов возможно, но не имеет а Генераторы множеств, стр, 149 Пустые фигурные скобки () используются для создания пустого словаря, как будет показано в следующем разделе. Множества Таблица 3.2. Методы и операторы множеств Описание Синтаксис Добавляет элементы х во множество в, если они от- сутствуют в в в.вбз(х) Удаляет все элементы из множества в в.с1еаг() в.ссру() Возвращает поверхностную пню множества в' коПазерхнсстнсэ и глубокое копирование, стр. 173 Возвращает новое множество, включающее элементы множества в, которые отсутствуют в множестве 1' в.б1тгегепсе(1) в Удаляет из множества в все элементы, присутствую- щие в множестве 1 в.стгтегепсе нрсзсе(1) в -= с Удаляет элемент х нз множества в, если он присутствует в множестве в; смотрите также метод ве1.
геисуе() в.01всагз(х) Возвращает новое множество, включающее элементы, присутствующие одновременно в множествах в и 1' в.тпсегвес11оп(1) в в с в. тпсегВЕСсщн ЗРбаСе(1) Оставляет во множестве в пересечение множеств в и 1 за=с власта)оспс(с) Возвращает Тгне, если множества в и с не имеют об- щих элементов' Возвращает Тгзе, если множество в эквивалентно множеству с нли является его подмножеством; чтобы проверить, является ли множество в только подмножеством множества 1, следует использовать проверку в < С' в, тввзьве1(1) в <= с Возвращает Тгне, если множество в эквивалентно мно.
жеству 1 или является его надмножеством; чтобы проверить, является лн множество в только надмножеством множества 1, следует использовать проверку в > 1' в.сввнрегвес(1) в >= 1 твующнй ему оператор (если таковой имеется) могут иксированным множествам. Этот метод н соответс также применять к ф Множества поддерживают встроенную функцию 1еп() и быструю проверку на вхождение с помощью операторов 1п и по1 сп. Они также предоставляют типичный набор операторов, как показано на рис.
3.4. Полный перечень методов и операторов, применимых к множествам, приводится в табл. 3.2. Все методы семейства впрс(а1еи (вес. нрбасв(), ве1. 1п1егвес11оп нрт)асе() и т. д.) могут принимать в качестве аргумента любые итерируемые объекты, но эквивалентные им комбинированные операторы присваивания ( ~ =, 6= и т. д.) требуют, чтобы оба операнда были множествами. 148 Глава 3. Типы коллекций Таблица 3.2 (продолжение) Синтаксис Описание Возвращает и удаляет случайный элемент множества в или возбуждает исключение КеуЕггог, если в — это пустое множество в.рор() Уделяет элемент х из множества в или возбуждает ис- ключение КеуЕггсг, если элемент х отсутствует в мно- жестве в; смотрите также метод вег.
о!всего() в.геасхе(х) Возвращает новое множество, включающее все эле- менты, присутствующие в множествах в и 1, за ис- ключением элементов, присутствующих в обоих мно- жествах одновременно' В Вуаавгг1С 011(егепсе(1) В 1 Возвращает в множестве в результат строгой дизь- юнкции множеств в и 1' в.вуааевг!с С!((егепсе Ррозге(1) в =1 Возвращает новое множество, включающее все эле- менты множества в к все элементы множества 1, от- сутствующие в множестве в' в спвсп(1) в~! в. эровге(1) в Добавляет во множество в все элементы множества 1, отсутствующие в множестве в Типичный случай использования множеств — когда необходимо орга- низовать быструю проверку на вхождение.
Например, нам может по- требоваться выводить на экран инструкцию о порядке использования программы, когда пользователь вводит аргументы «-Ь» или « — Ье1р»! х( 1еп(вув.вгд») == 1 сг вув.агдх(11!п ("-П", "--Пе1р"): вееп = вег() Гог хр 1п !Рв; 1( 1р по! 1п вееп: вееп.взо(хр) Гсг !Р 1и ве((!Рв): ргссевв 1Р(1Р) ргссевв 1Р(!Р) Другой типичный случай использования множеств — когда необходимо избежать обработки повторяющихся элементов данных.
Например, предположим, что имеется итерируемый объект (такой как список), содержащий 1Р-адреса, извлеченные из файлов журнала веб-сервера, и необходимо выполнить некоторые действия, причем не более одного раза для каждого отдельного 1Р-адреса. Допустим, что 1Р-адреса сохраняются в хешируемом и итерируемом объекте 1рв и что для каждого адреса должна вызываться функция ргосевв 1р(), которая уже определена. Тогда следующие фрагменты программного кода сделают то, что нам требуется, хотя и немного по-разному: 149 Множества Во фрагменте слева, если очередной 1Р-адрес еще не обрабатывался, он добавляется во множество яееп и обрабатывается, в противном случае адрес пропускается. В фрагменте справа мы изначально имеем дело только с уникальными 1Р-адресами. Различие между этими фрагментами заключается, во-первых, в том, что в левом фрагменте создается множество яееп, необходимость в котором отсутствует в правом фрагменте, и, во-вторых, в левом фрагменте 1Р-адреса обрабатываются в порядке, в каком они присутствуют в объекте (ря, тогда как в правом фрагменте они обрабатываются в произвольном порядке.
Фрагмент справа выглядит проще, но, если порядок обработки элементов объекта 1ря имеет значение, придется использовать фрагмент слева или изменить первую строку во фрагменте справа — например, так: гсг (р ап яоггее(яег((ря)):, если этого будет достаточно, чтобы получить желаемый порядок следования. Теоретически фрагмент справа может оказаться более медленным при большом количестве элементов в объекте зря, поскольку в нем множество создается целиком, а не с определенным шагом.