Объекты множества в языке Python представляют собой неупорядоченные контейнеры
(см. подраздел 1.1 лаб. раб. №3) уникальных хэшируемых
объектов.
Объект является хэшируемым, если он имеет значение хэш-функции,
которое не меняется в течение времени существования объекта, т.е. поддерживает метод
__hash__() и может быть сравним с другими объектами с помощью метода
__eq__()
(см. подраздел 1.3 лаб. раб. №3). Все хэшируемые объекты
являются неизменяемыми объектами и принадлежат ABC-классу Hashable (см.
раздел 1 лаб. раб. №3).
Хэшируемость объектов позволяет использовать их в качестве элементов
множества и ключей словарей (см. подраздел 2.1), поскольку эти структуры данных
используют значения хэш-функции.
В языке Python все встроенные неизменяемые объекты (такие, как числа,
логические значения, строки и кортежи) являются хэшируемыми:
>>>
from
collections
import
Hashable
>>>
isinstance
(1.25e-1, Hashable)
True
>>>
isinstance
(
False
, Hashable)
True
>>>
isinstance
(
'Web'
, Hashable)
True
>>>
isinstance
((1,2,3),collections.Hashable)
True
в то время как изменяемые контейнеры, такие как изменяемые множества
(см. подраздел 1.1), словари (см. подраздел 2.1) и списки
(см. раздел 2 лаб. раб. №3) – нет:
>>>
isinstance
([
'a'
,
'b'
,
'c'
], Hashable
False
Объекты, которые являются экземплярами созданных пользователем
классов, являются хэшироваными по умолчанию, при сравнении между собой они не равны и значения их
хэшей являются значениям их id().
Объекты множества могут быть использованы при проверке на наличие
элементов в последовательности, при удалении дубликатов из последовательности и при выполнении
математических операций над множествами, таких как объединение, пересечение и вычитание.
Имеется два встроенных типа (класса) множеств:
set и frozenset
(см. подраздел 2.1).
Тип set является изменяемым множеством или
просто множеством. Как изменяемый объект, он не может быть использован ни в качестве ключа в
словарях, ни в качестве элемента другого множества.
Тип frozenset является неизменяемым
множеством. Поэтому может быть ключом в словаре и элементом другого множества.
Создавать экземпляры изменяемого множества (тип set) можно с помощью
литерала, поместив в фигурные скобки элементы множества неизменяемых типов, разделенные запятыми:
>>>
a_set={1,2,
'a'
,
'b'
}
>>>
a_set
{'b', 1, 2, 'a'},
или с помощью генератора элементов множества (см. подраздел 3.2).
Проверим изменяемость (нехэшируемость) множеств:
>>>
isinstance
(a_set, Hashable)
False.
Также для создания множества можно использовать конструктор –
встроенную функцию set([iterable])
(см. подраздел 8.1 лаб. раб. №1), аргументом которой является
итерабельный объект. Поэтому в объекты множества можно преобразовать такие последовательности, как
строки, списки, кортежи и диапазоны. Если строка, список, кортеж или
диапазон содержат одинаковые элементы, после преобразования из них останется только один:
>>>
set
(
'ABBA'
)
{'B','A'}.
Отметим, что, поскольку множество является неупорядоченным
контейнером, то и элементы полученного множества могут указываться интерпретатором в произвольном
порядке.
Раз элементы множества не могут быть изменяемыми типами, то и
итерабельный тип, указанный в качестве аргумента функции set() не может
содержать изменяемые (нехэшируемые) элементы:
>>>
set
([1,2,[3,4]])
TypeError: unhashable type: 'list'
Для создания объектов множества неизменяемого типа
frozenset необходимо использовать конструктор – встроенную функцию frozenset()
(см. подраздел 8.1 лаб. раб. №1,
аргументом которой является итерабельный объект:
>>>
frozenset
((
'a'
,
'c'
,
'd'
,
'c'
))
frozenset({'d', 'a', 'c'})
.
Экземпляры типов set и
frozenset, являясь контейнерами:
>>>
import
collections
>>>
isinstance
({1,2},collections.Container)
True
>>>
isinstance
(frozenset({1,2}), collections.Container)
True
и не являясь последовательностями:
>>>
isinstance
({1,2},collections.Sequence)
False
>>>
isinstance
(frozenset({1,2}), collections.Sequence)
False
поддерживают лишь часть операций, свойственных последовательностям (те из них, которые также
поддерживают и контейнеры):
Можно добавить, что объекты изменяемого множества set принадлежат
ABC-классу MutableSet:
>>>
s={1,2,3}
>>>
isinstance
(s,collections.MutableSet)
True,
а объекты неизменяемого класса frozenset – нет:
>>>
fs=frozenset(s)
>>>
isinstance
(fs,collections.MutableSet)
False
Имеется два способа добавления элементов в существующее множество:
Отметим, что объекты типа frozenset, будучи неизменяемыми множествами, не имеют методов добавления элементов к множеству.
Имеется несколько способов удаления элементов из существующего множества:
В логическом контексте пустое множество set() соответствует False,
любое другое – True.
Отметим, что объекты типа frozenset, будучи
неизменяемыми множествами, не имеют методов удаления элементов из множества.
Python имеет несколько методов сравнения множеств:
Метод copy() используется для "поверхностного" копирования списков
(см. раздел 4)): Python имеет несколько методов для выполнения основных операций над множествами:
Словари в языке Python имеют тип (класс) dict и представляют собой
множество пар вида ключ:значение. Словари в языке Python похожи на
ассоциативные массивы языка Jaxascript.
Для создания словаря в виде литерала необходимо поместить его элементы, заданные в виде пар
ключ:значение и разделеные запятыми, в фигурные скобки: Выше четырьмя разными способами были созданы словари a_dict(),
b_dict(), c_dict() и
d_dict(), имеющие одно и то же значение. Проверим это: который имеет тип zip: и добавлять новые пары в словарь: Словари поддерживают следующие методы:
В литералах при создании списков, множеств и словарей помимо указания перечня их элементов
(см. подразделы 2.1 лаб. раб. №3, 1.1 и
2.1) можно также указать генераторы элементов этих контейнеров.
Например, создание списка кубов целых чилел от 1 до 10 можно осуществить следующим образом:
Создадим с помощью генератора множество букв, из которых состоит предложение
"Карл украл у Клары кораллы", представив их в верхнем регистре: В качестве последнего примера использования генераторов рассмотрим создание словаря, ключами
которого являются числа, заданные в списке, а значениями – квадратные корни этих чисел: В подразделе 1.4 при описании метода copy() был
использован термин поверхностная копия. Поскольку существует еще и глубокая копия, дадим
разъяснение этим терминам. Различие между между поверхностным (англ. shallow) и глубоким (англ. deep) копированием
имеет смысл только для составных объектов (объектов, которые содержат другие объекты, например,
списки, словари или экземпляры классов):
В качестве примера создадим и сравним поверзностную и глубокую копию словаря: Разработать программу на языке Python, которая выполняет следующее:
Таблица 1 – Перечень индивидуальных заданий
>>>
b_set=a_set.copy()
>>>
b_set
{1, 2, 5, 6}.
1.5 Операции над множествами
>>>
a_set={1,2,5,6,9}
>>>
b_set={2,4,6,8}
>>>
a_set.union(b_set)
{1, 2, 4, 5, 6, 8, 9},
метод симметричен, т.е. a_set.union(b_set)=b_set.union(a_set):
>>>
b_set.union(a_set)
{1, 2, 4, 5, 6, 8, 9};
>>>
a_set.intersection(b_set)
{2, 6},
метод симметричен;
>>>
a_set.difference(b_set)
{9, 5, 1},
этот метод не симметричен, поскольку a_set.difference(b_set) не равно b_set.difference(a_set):
>>>
b_set.difference(a_set)
{8, 4};
>>>
a_set.symmetric_difference(b_set)
{1, 4, 5, 8, 9},
метод симметричен.
2 Словари
2.1 Создание словарей
>>>
a_dict={
'alpha'
:1,
'beta'
:2,
'gamma'
:3}
>>>
a_dict
{'alpha': 1, 'beta': 2, 'gamma': 3}
В качестве ключа необходимо использовать только неизменяемые
(хэшируемые) типы: числа (целые и с плавающей точкой), строки, логические значения, кортежи,
диапазоны и неизменяемые множества. В качестве значения могут быть заданы любые из рассмотренных
типов, включая изменяемые множества и словари.
Словари также можно задавать с помощью конструктора – встроенной
функции dict()
(см. подраздел 8.1 лаб. раб. №1). Если при
вызове функция не имеет аргументов, то создается пустой список:
>>>
dict
()
{},
если имеет, то для создания словаря могут быть использованы следующие варианты задания аргументов:
>>>
b_dict=
dict
(alpha=1, beta=2, gamma=3);
>>>
c_dict=
dict
({
'gamma'
:3,
'alpha'
:1,
'beta'
:2}) ;
>>>
d_dict=
dict
([(
'alpha'
,1), (
'beta'
,2), (
'gamma'
,3)])
>>>
a_dict==b_dict==c_dict==d_dict
True.
Если ключи и значения словаря заданы последовательностями, то для
создания словаря также можно использовать встроенную функцию
zip(*iterable)
(см. подраздел 8.1 лаб. раб. №1), которая
возвращает итератор, элементами которого являются кортежи, где i-й кортеж содержит i-е элементы
каждого аргумента последовательностей или итерабельных объектов.
Если последовательности, явдяющиеся аргументами функции, имеют разную длину, то формируемые кортежи
имеют число элементов, равное длине минимальной последовательности. Если указан один элемент –
функция возвращает итератор, состоящий из одноэлементных кортежей. Если аргументы не указаны –
возвращается пустой итератор.
Пусть, например, ключи словаря представлены списком
key_list, а значения – кортежом
value_tuple:
>>>
key_list=[
'a'
,
'b'
,
'c'
]
>>>
value_tuple=(1.32,
'value'
, [1,2,3], 25)
Теперь с помощью функции zip(), аргументами
которой являются последовательности key_list и
value_tuple, создаем итератор с именем zipped:
>>>
zipped=
zip
(key_list, value_tuple),
>>>
type
(zipped)
<class 'zip'>
Остается только преобразовать его с помощью конструктора в словарь:
>>>
e_dict=
dict
(zipped)
>>>
e_dict
{'a': 1.32, 'b': 'value', 'c': [1, 2, 3]}
Следует сказать, что словари в настоящее время являются единственными
представителями ABC-класса Mapping, объекты которого ставят в
соответсвие неизменяемые значения произвольным объектам. Являются изменяемыми контейнерами типа
Mapping:
>>>
import
collections
>>>
isinstance
({1:
'a'
,2:
'b'
,3:
'c'
},collections.Container)
True
>>>
isinstance
({1:
'a'
,2:
'b'
,3:
'c'
},collections.Mapping)
True
>>>
isinstance
({1:
'a'
,2:
'b'
,3:
'c'
},collections.MutableMapping)
True
Для получения значения словаря по ключу нобходимо воспользоваться
выражением:
>>>
a_dict[
'beta'
]
2,
если указанный ключ отсутствует – возбуждается исключение KeyError:
>>>
a_dict[
'delta'
]
KeyError: 'delta'.
Чтобы получить все значения словаря следует использовать оператор
for in:
>>>
for
key
in
a_dict:
print
(key,
'='
,a_dict[key])
alpha = 1
beta = 2
gamma = 3
Можно изменять значение ключа:
>>>
a_dict[
'alpha'
]=11
>>>
a_dict
{'alpha': 11, 'beta': 2, 'gamma': 3}
>>>
a_dict[
'epsilon'
]=5
>>>
a_dict
{'alpha': 22, 'beta': 2, 'gamma': 3, 'epsilon': 5}
Для удаления ключа необходимо указать:
>>>
del
a_dict[
'alpha'
]
>>>
]
{'beta': 2, 'gamma': 3, 'epsilon': 5}.
Словари так же, как последовательности и множества поддерживают
функцию определения числа элементов len() и оператор
in, позволяющий определить принадлежность элемента контейнеру.
Пустой словарь – {} в логическом контексте равен False, все
остальные словари – True.
2.2 Методы словарей
>>>
b_dict={1:101, 2:102, 3:103}
>>>
b_dict.clear()
>>>
a_dict
{}.
Метод clear() поддерживается всеми изменяемыми классами данных;
>>>
b_dict=a_dict.copy()
>>>
b_dict
{'beta': 2, 'gamma': 3, 'epsilon': 5}.
Метод copy() поддерживается всеми изменяемыми классами данных;
>>>
a_dict.get(
'gamma'
,
'new_key'
)
'gamma'
>>>
a_dict.get(
'delta'
,
'new_key'
)
'new_key';
>>>
items=a_dict.items()
>>>
items
dict_items([('epsilon', 5), ('beta', 2), ('gamma', 3)])
>>>
a_dict.keys()
dict_keys(['beta', 'gamma', 'epsilon'])
>>>
a_dict.pop(
'gamma'
)
3
>>>
a_dict
{'beta': 2, 'delta': 4, 'epsilon': 5}
;
>>>
a_dict.setdefault(
'delta'
,
4
)
4
>>>
a_dict
{'beta': 2, 'delta': 4, 'epsilon': 5}
>>>
b_dict={
'figure'
:
'circle'
,
'color'
:
'green'
}
>>>
a_dict.update(b_dict)
>>>
a_dict
{'beta': 2, 'figure': 'circle', 'delta': 4, 'color': 'green', 'epsilon': 5}
>>>
a_dict.values
dict_values([2, 'circle', 4, 'green', 5]).
3 Генераторы
3.1 Использование генератора для формирования списка
>>>
a_list=[x**3
for
x
in
range
(1, 11)]
>>>
a_list
[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000].
Выражение x**3 for x in range(1,11)
является генераторным выражением. Оно имеет тип генератора:
>>>
type
(x**3
for
x
in
range
(1, 11))
<class 'generator'>
и состоит из выражения x**3, за которым следует оператор
for для итерабельного типа. В таком виде генераторное выражение может
использоваться только в качестве единичного аргумента в функциях. В остальных случаях необходимо
указывать его в скобках, например при анализе, является ли тип generator
итерабельным:
>>>
import
collections
>>>
isinstance
((x**3
for
x
in
range
(1, 11)), collections.Iterable)
True.
В приведенном примере сформированные кубы целых чисел сохранены в
памяти в виде списка. Для длинных последовательностей это не всегда удобно. Рассмотрим вариант
генерации кубов чисел без сохранения их в памяти:
>>>
gen=(x**3
for
x
in
range
(1, 11))
>>>
for
x
in
gen:
print
x, end=
' '
)
1, 8, 27, 64, 125, 216, 343, 512, 729, 1000.
Поскольку значения генератора gen не
сохранены в памяти повторное его использование ничего не дает:
>>>
for
x
in
gen:
print
x, end=
' '
)
3.2 Использование генератора для формирования множества
>>>
a_set={x
for
x
in
'Карл украл у Клары кораллы'
.upper()}
>>>
a_set
{'О', 'Л', 'К', 'А', ' ', 'Ы', 'Р', 'У'}
.
3.3 Использование генератора для формирования словаря
>>>
{x:x**(1/2)
for
x
in
[2, 5, 25] }
{25: 5.0, 2: 1.4142135623730951, 5: 2.23606797749979}.
Формировать элементы последовательностей также можно с использованием
встроенной функции map()
(см. подраздел 1.5.2 лаб. раб. №6).
4 Копирование объектов
Операторы присваивания в языке Python не копируют объекты, они только
сооздают ссылки на объект. Для контейнеров, которые являются изменяемыми или содержат изменяемые
элементы, возникает иногда необходимость их копирования – чтобы можно было изменить копию, не
изменяя исходные значения.
Модуль copy содержит два метода:
>>>
import
copy
>>>
a_dict={1:5,2:{3:25}}
>>>
a_dict
{1: 5, 2: {3: 25}}
>>>
b_dict=copy.copy(a_dict)
>>>
b_dict
{1: 5, 2: {3: 25}}
>>>
b_dict[2][3]=77
>>>
a_dict
{1: 5, 2: {3: 77}}.
Видно, что при использовании поверхностного копирования словаря
(функции copy()) изменения в полученной копии привели к изменению оригинала. При использовании
глубокого копирования (функции deepcopy()) этого не произойдет:
>>>
a_dict={1:5,2:{3:25}}
>>>
c_dict=copy.deepcopy(a_dict)
>>>
c_dict[2][3]=77
>>>
a_dict
{1: 5, 2: {3: 25}}.
Для создания "поверхностной" копии помимо метода
copy() модуля copy() можно также использовать:
Индивидуальные задания
Номер
п/пМножество Словарь
Создание Методы Операции Создание Методы
1 3 1,3 4 1 2,5,8
2 2 1,4 3 2 2,6,9
3 1 1,5 2 3 3,5,1
4 3 2,3 1 4 3,6,8
5 2 2,4 4 5 4,5,9
6 1 2,5 3 1 4,6,1
7 3 1,3 2 2 7,9,5
8 2 1,4 1 3 2,5,8
9 1 1,5 4 4 2,6,9
10 3 2,3 3 5 3,5,1
11 2 2,4 2 1 3,6,8
12 1 2,5 1 2 4,5,9
13 3 1,3 4 3 4,6,1
14 2 1,4 3 4 7,9,5
15 1 1,5 2 5 2,5,8
16 3 2,3 1 1 2,6,9
17 2 2,4 4 2 3,5,1
18 1 2,5 3 3 3,6,8
19 3 1,3 2 4 4,5,9
20 2 1,4 1 5 4,6,1