## ++Тема 3++<br>Коллекции
(c) Яценко Р.Н., 2019-2022
[Учебный центр компьютерных технологий "Кит"](http://kit.kh.ua/)
<img src="https://i.imgur.com/Kh901c1.png" style="width: 150px; position: fixed; top: 10px; right: 10px; border: 0; box-shadow: none;">
---
## 1. Основные понятия
----
### Определение
Коллекция
: программный объект (переменная-контейнер), хранящая набор значений одного или различных типов, позволяющий обращаться к этим значениям, а также применять специальные функции и методы, зависящие от типа коллекции
----
### Классификация

----
### Свойства
Индексированность
: каждый элемент коллекции имеет свой порядковый номер -- индекс. Это позволяет обращаться к элементу по его порядковому индексу, выполнять срезы
Уникальность
: каждый элемент коллекции может встречаться в ней только один раз
Изменяемость коллекции
: позволяет добавлять в коллекцию новые элементы или удалять их
----
### Сравнение свойств

----
### Примечание для словаря (dict)
- сам словарь изменяем -- можно добавлять/удалять новые пары `ключ: значение`
- значения элементов словаря -- изменяемые и не уникальные
- ключи -- не изменяемые и уникальные, поэтому, например, мы не можем сделать ключом словаря список, но можем кортеж. Из уникальности ключей, так же следует уникальность элементов словаря -- пар
`ключ: значение`
---
## 2. Общие подходы к работе с любой коллекцией
----
### Печать элементов коллекции
``` python=
# Зададим исходные список и словарь
my_list = ['a', 'b', 'c', 'd', 'e', 'f']
my_dict = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6}
print(my_list)
# ['a', 'b', 'c', 'd', 'e', 'f']
print(my_dict)
# {'a': 1, 'c': 3, 'e': 5, 'f': 6, 'b': 2, 'd': 4}
# Не забываем, что порядок элементов
# в неиндексированных коллекциях не сохраняется
```
----
### Подсчёт количества элементов коллекции
``` python=
print(len(my_list))
# 6
print(len(my_dict))
# 6 - для словаря пара ключ-значение считаются одним элементом.
print(len('ab c'))
# 4 - для строки элементом является 1 символ
```
----
### Проверка принадлежности элемента коллекции
- `x in s` -- вернет `True`, если элемент входит в коллекцию `s` и `False` -- если не входит
- `x not in s` -- вариант проверки непринадлежности:
``` python=
my_list = ['a', 'b', 'c', 'd', 'e', 'f']
print('a' in my_list) # True
print('q' in my_list) # False
print('a' not in my_list) # False
print('q' not in my_list) # True
```
----
### Для словаря и строки
``` python=
my_dict = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6}
print('a' in my_dict)
# True - без указания метода поиск по ключам
print('a' in my_dict.keys())
# True - аналогично примеру выше
print('a' in my_dict.values())
# False - так как 'а' — ключ, не значение
print(1 in my_dict.values())
# True
# Можно ли проверять пары? Можно!
print(('a',1) in my_dict.items()) # True
print(('a',2) in my_dict.items()) # False
# Для строки можно искать не только один символ, но и подстроку:
print('ab' in 'abc') # True
```
----
### Обход всех элементов коллекции в цикле for in
В данном случае, в цикле будут последовательно перебираться элементы коллекции, пока не будут перебраны все из них:
``` python=
for elm in my_list:
print(elm)
```
----
### Для словаря
``` python=
# При таком обходе словаря, перебираются только ключи
# равносильно for elm in my_dict.keys()
for elm in my_dict:
print(elm)
# При желании можно пройти только по значениям
for elm in my_dict.values():
print(elm)
# Но чаще всего нужны пары ключ(key) — значение (value)
for key, value in my_dict.items():
# Проход по .items() возвращает кортеж (ключ, значение),
# который присваивается кортежу переменных key, value
print(key, value)
```
----
### Возможная ошибка
- *Не меняйте количество элементов коллекции в теле цикла в этой же коллекции!*
- Чтобы избежать подобных побочных эффектов, можно, например, перебирать копию коллекции:
``` python
for elm in list(my_list):
# Теперь можно удалять и добавлять элементы в my_list,
# так как цикл идет по его копии
```
----
### Функции min(), max(), sum()
- Функции `min()`, `max()` -- поиск минимального и максимального элемента соответственно -- работают не только для числовых, но и для строковых значений
- `sum()` -- суммирование всех элементов, если они все числовые
``` python=
print(min(my_list)) # a
print(sum(my_dict.values())) # 21
```
---
## 3. Общие методы для коллекций
----
### Таблица методов

----
### Метод count
`.count()` -- метод подсчета определенных элементов для неуникальных коллекций (строка, список, кортеж), возвращает сколько раз элемент встречается в коллекции
``` python=
my_list = [1, 2, 2, 2, 2, 3]
print(my_list.count(2))
# 4 экземпляра элемента равного 2
print(my_list.count(5))
# 0 - то есть такого элемента в коллекции нет
```
----
### Метод index
`.index()` -- возвращает минимальный индекс переданного элемента для индексированных коллекций (строка, список, кортеж)
``` python=
my_list = [1, 2, 2, 2, 2, 3]
print(my_list.index(2))
# первый элемент равный 2 находится по индексу 1
# (индексация с нуля!)
print(my_list.index(5))
# ValueError: 5 is not in list
# отсутствующий элемент выдаст ошибку!
```
----
### Метод copy
`.copy()` -- метод возвращает неглубокую (не рекурсивную) копию коллекции (список, словарь, оба типа множества)
``` python=
my_set = {1, 2, 3}
my_set_2 = my_set.copy()
print(my_set_2 == my_set)
# True - коллекции равны - содержат одинаковые значения
print(my_set_2 is my_set)
# False - коллекции не идентичны, это разные объекты с разными id
```
----
### Метод clear
`.clear()` -- метод изменяемых коллекций (список, словарь, множество), удаляющий из коллекции все элементы и превращающий её в пустую коллекцию
``` python=
my_set = {1, 2, 3}
print(my_set) # {1, 2, 3}
my_set.clear()
print(my_set) # set()
```
---
## 4. Конвертация одного типа коллекции в другой
----
### Преобразование типов
Один тип коллекции можно конвертировать в другой тип коллекции. Для этого, как правило достаточно передать одну коллекцию в функцию создания другой:
``` python=
my_tuple = ('a', 'b', 'a')
my_list = list(my_tuple)
my_set = set(my_tuple)
# теряем индексы и дубликаты элементов!
my_frozenset = frozenset(my_tuple)
# теряем индексы и дубликаты элементов!
print(my_list, my_set, my_frozenset)
# ['a', 'b', 'a'] {'a', 'b'} frozenset({'a', 'b'})
```
----
### Возможна потеря данных
- При преобразовании в множество теряются дублирующие элементы, так как множество содержит только уникальные элементы
- При конвертации индексированной коллекции в неиндексированную теряется информация о порядке элементов
- После конвертации в неизменяемый тип, мы больше не сможем менять элементы коллекции -- удалять, изменять, добавлять новые
----
### Конвертация в словарь
- Способом выше не получится создать словарь, так как он состоит из пар
`ключ: значение`
- Это ограничение можно обойти, создав словарь комбинируя ключи со значениями с использованием `zip()`
``` python=
my_keys = ('a', 'b', 'c')
my_values = [1, 2]
# Если количество элементов разное
# будет отработано пока хватает на пары - лишние отброшены
my_dict = dict(zip(my_keys, my_values))
print(my_dict) # {'a': 1, 'b': 2}
```
----
### Создаем строку из другой коллекции
``` python=
my_tuple = ('a', 'b', 'c')
my_str = ''.join(my_tuple)
print(my_str) # abc
```
----
### Возможная ошибка
Если Ваша коллекция содержит изменяемые элементы (например, список списков), то ее нельзя конвертировать в неизменяемую коллекцию, так как ее элементы могут быть только не изменяемыми!
``` python=
my_list = [1, [2, 3], 4]
my_set = set(my_list)
# TypeError: unhashable type: 'list'
```
---
## 5. Индексирование
----
### Индексированные коллекции
- *Индексированные коллекции* (их еще называют *последовательности* -- sequences):
- список (list)
- кортеж (tuple)
- строка (string)
- Под индексированностью имеется ввиду, что элементы коллекции располагаются в определённом порядке, каждый элемент имеет свой индекс от 0 до индекса на единицу меньшего длины коллекции (`len(mycollection)-1`)
----
### Получение значения по индексу
- Можно задавать отрицательный индекс, это значит, что будем находить элемент с конца считая в обратном порядке
- При задании отрицательного индекса, последний элемент имеет индекс -1, предпоследний -2 и так далее до первого элемента индекс которого равен значению длины коллекции с отрицательным знаком, то есть `-len(mycollection)`
----
### Таблица индексов
| | | | | | |
|-------- |:-----:|:-----:|:-----:|:-----:|:-----:|
|Строка S | H | e | l | l | o |
|Индекс | S[0] | S[1] | S[2] | S[3] | S[4] |
|Индекс | S[-5] | S[-4] | S[-3] | S[-2] | S[-1] |
----
### Вложенные списки
Коллекции могут иметь несколько уровней вложенности, как список списков в примере ниже. Для перехода на уровень глубже ставится вторая пара квадратных скобок и так далее:
``` python=
my_2lvl_list = [[1, 2, 3], ['a', 'b', 'c']]
print(my_2lvl_list[0])
# [1, 2, 3] - первый элемент — первый вложенный список
print(my_2lvl_list[0][0])
# 1 — первый элемент первого вложенного списка
print(my_2lvl_list[1][-1])
# с — последний элемент второго вложенного списка
```
----
### Обращение к элементу списка по индексу
Поскольку кортежи и строки неизменяемые коллекции, то по индексу мы можем только брать элементы, но не менять их:
``` python=
my_tuple = (1, 2, 3, 4, 5)
print(my_tuple[0]) # 1
my_tuple[0] = 100
# TypeError: 'tuple' object does not support item assignment
```
----
### Изменение элемента списка по индексу
- Для списка, если взятие элемента по индексу располагается в левой части выражения, а далее идёт оператор присваивания `=`, то мы задаём новое значение элементу с этим индексом:
``` python=
my_list = [1, 2, 3, [4, 5]]
my_list[0] = 10
my_list[-1][0] = 40
print(my_list) # [10, 2, 3, [40, 5]]
```
----
- Для такого присвоения, элемент уже должен существовать в списке, нельзя таким образом добавить элемент на несуществующий индекс:
``` python=
my_list = [1, 2, 3, 4, 5]
my_list[5] = 6 # IndexError: list assignment index out of range
```
---
## 6. Срезы
----
### Синтаксис среза
- Очень часто, надо получить не один какой-то элемент, а некоторый их набор ограниченный определенными простыми правилами удобнее использовать так называемый *срез* (slice, slicing)
- Следует помнить, что взяв элемент по индексу или срезом (slice) мы не как не меняем исходную коллекцию, мы просто скопировали ее часть для дальнейшего использования (применимо ко всем последовательностям)
----
Синтаксис среза похож на таковой для индексации, но в квадратных скобках вместо одного значения указывается 2-3 через двоеточие:
``` python
my_collection[start:stop:step] # старт, стоп и шаг
```
----
### Особенности среза
- Отрицательные значения старта и стопа означают, что считать надо не с начала, а с конца коллекции
- Отрицательное значение шага -- перебор ведём в обратном порядке справа налево
- Если не указан старт `[:stop:step]` -- начинаем с самого края коллекции, то есть с первого элемента (включая его), если шаг положительный или с последнего (включая его), если шаг отрицательный
----
- Если не указан стоп `[start::step]` -- идем до самого края коллекции, то есть до последнего элемента (включая его), если шаг положительный или до первого элемента (включая его), если шаг отрицательный
- `step = 1`, то есть последовательный перебор слева направо указывать не обязательно -- это значение шага по умолчанию. В таком случае достаточно указать `[start:stop]`
- Можно сделать даже так `[:]` -- это значит взять коллекцию целиком
----
**ВАЖНО**: При срезе, первый индекс входит в выборку, а второй нет:
```
[ <первый включаемый> : <первый НЕ включаемый> : <шаг> ]
```
----
### Примеры срезов в виде таблицы

----
### Именованные срезы
Чтобы избавится от «магических констант», особенно в случае, когда один и тот же срез надо применять многократно, можно задать константы с именованными срезами с пользованием специальной функции `slice()`
``` python=
person = ('Alex', 'Smith', "May", 10, 1980)
NAME, BIRTHDAY = slice(None, 2), slice(2, None)
# задаем константам именованные срезы
# данные константы в квадратных скобках
# заменятся соответствующими срезами
print(person[NAME]) # ('Alex', 'Smith')
print(person[BIRTHDAY]) # ('May', 10, 1980)
my_list = [1, 2, 3, 4, 5, 6, 7]
EVEN = slice(1, None, 2)
print(my_list[EVEN]) # [2, 4, 6]
```
----
### Изменение списка срезом
- Даже если хотим добавить один элемент, необходимо передавать итерируемый объект, иначе будет ошибка `TypeError: can only assign an iterable`
``` python=
my_list = [1, 2, 3, 4, 5]
# my_list[1:2] = 20 # TypeError: can only assign an iterable
my_list[1:2] = [20] # Вот теперь все работает
print(my_list) # [1, 20, 3, 4, 5]
```
- Для вставки одиночных элементов лучше использовать методы списка `.append()` и `.insert()`
----
- Можно менять части последовательности -- это применение выглядит наиболее интересным, так как решает задачу просто и наглядно:
``` python=
my_list = [1, 2, 3, 4, 5]
my_list[1:3] = [20, 30]
print(my_list) # [1, 20, 30, 4, 5]
my_list[1:3] = [0] # заменяем два элемента на один
print(my_list) # [1, 0, 4, 5]
my_list[2:] = [40, 50, 60] # или два элемента на три
print(my_list) # [1, 0, 40, 50, 60]
```
- Можно просто удалить часть последовательности:
``` python=
my_list = [1, 2, 3, 4, 5]
my_list[:2] = [] # или del my_list[:2]
print(my_list) # [3, 4, 5]
```
----
### Выход за границы индекса
- Обращение к несуществующему индексу коллекции вызывает ошибку:
``` python=
my_list = [1, 2, 3, 4, 5]
print(my_list[-10])
# IndexError: list index out of range
print(my_list[10])
# IndexError: list index out of range
```
- А в случае среза ошибки не происходит:
``` python=
my_list = [1, 2, 3, 4, 5]
print(my_list[0:10])
# [1, 2, 3, 4, 5] — отработали в пределах коллекции
print(my_list[10:100])
# [] - таких элементов нет — вернули пустую коллекцию
print(my_list[10:11])
# [] - пустая коллекция, без ошибки
```
---
## 7. Сортировка элементов коллекции
----
### Функция sorted()
- функция не меняет исходную коллекцию, а возвращает новый список из ее элементов
- не зависимо от типа исходной коллекции, вернётся список (list) ее элементов
- поскольку она не меняет исходную коллекцию, ее можно применять к неизменяемым коллекциям
- поскольку при сортировке возвращаемых элементов нам не важно, был ли у элемента некий индекс в исходной коллекции, можно применять к неиндексированным коллекциям
----
### Дополнительные необязательные аргументы
- `reverse=True` -- сортировка в обратном порядке
- `key=funcname` -- сортировка с помощью функции `funcname` (стандартная функция Python или специально написанная вами)
``` python=
my_list = [2, 5, 1, 7, 3]
my_list_sorted = sorted(my_list)
print(my_list_sorted) # [1, 2, 3, 5, 7]
my_set = {2, 5, 1, 7, 3}
my_set_sorted = sorted(my_set, reverse=True)
print(my_set_sorted) # [7, 5, 3, 2, 1]
```
----
### Пример сортировки списка строк по длине len() каждого элемента
``` python=
my_files = ['somecat.jpg', 'pc.png', 'apple.bmp', 'mydog.gif']
my_files_sorted = sorted(my_files, key=len)
print(my_files_sorted)
# ['pc.png', 'apple.bmp', 'mydog.gif', 'somecat.jpg']
```
----
### Функция reversed()
Применяется для последовательностей и работает по другому:
- возвращает генератор списка, а не сам список
- если нужно получить готовый список, то результат можно обернуть в list() или вместо reversed() воспользоваться срезом [: :-1]
- она не сортирует элементы, а возвращает их в обратном порядке
- если у нас коллекция неиндексированная, то эта функция к таким коллекциям не применима
----
### Примеры для функции reversed()
``` python=
my_list = [2, 5, 1, 7, 3]
my_list_sorted = reversed(my_list)
print(my_list_sorted)
# <listreverseiterator object at 0x7f8982121450>
print(list(my_list_sorted))
# [3, 7, 1, 5, 2]
print(my_list[::-1])
# [3, 7, 1, 5, 2] - тот же результат с помощью среза
```
----
### Методы списка .sort() и .reverse()
У списка (и только у него) есть особые методы `.sort()` и `.reverse()` которые делают тоже самое, что соответствующие функции `sorted()` и `reversed()`, но при этом:
- меняют сам исходный список, а не генерируют новый
- возвращают `None`, а не новый список
- поддерживают те же дополнительные аргументы
- в них не надо передавать сам список первым параметром
----
### Примеры методов .sort() и .reverse()
``` python=
my_list = [2, 5, 1, 7, 3]
my_list.sort()
print(my_list)
# [1, 2, 3, 5, 7]
my_list = my_list.sort()
print(my_list) # None
```
----
### Особенности сортировки словаря
- `sorted(my_dict)` -- идёт перебор только ключей, сортированный список ключей нам и возвращается
- `sorted(my_dict.keys())` -- тот же результат, что в предыдущем примере
- `sorted(my_dict.items())` -- возвращается сортированный список кортежей (ключ, значение), сортированных по ключу
- `sorted(my_dict.values())` -- возвращается сортированный список значений
----
### Примеры сортировки словаря
``` python=
my_dict = {'a': 1, 'c': 3, 'e': 5, 'f': 6, 'b': 2, 'd': 4}
mysorted = sorted(my_dict)
print(mysorted)
# ['a', 'b', 'c', 'd', 'e', 'f']
mysorted = sorted(my_dict.items())
print(mysorted)
# [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6)]
mysorted = sorted(my_dict.values())
print(mysorted)
# [1, 2, 3, 4, 5, 6]
```
---
## 8. Объединение последовательностей и словарей
----
### Объединение строк (string) и кортежей (tuple)
Используется оператор сложения "+"
``` python=
str1 = 'abc'
str2 = 'de'
str3 = str1 + str2
print(str3) # abcde
tuple1 = (1, 2, 3)
tuple2 = (4, 5)
tuple3 = tuple1 + tuple2
print(tuple3) # (1, 2, 3, 4, 5)
```
----
### Объединение списков (list)
Используется оператор сложения "+"
``` python=
a = [1, 2, 3]
b = [4, 5]
c = a + b
print(a, b, c)
# [1, 2, 3] [4, 5] [1, 2, 3, 4, 5]
c = a + [b]
print(a, b, c)
# [1, 2, 3] [4, 5] [1, 2, 3, [4, 5]]
```
----
### Объединение словарей (dict)
Сложить два словаря чтобы получить третий оператором `+` Python не позволяет «TypeError: unsupported operand type(s) for +: 'dict' and 'dict'
Это можно сделать комбинируя методы `.copy()` и `.update()`:
``` python=
dict1 = {'a': 1, 'b': 2}
dict2 = {'c': 3, 'd': 4}
dict3 = dict1.copy()
dict3.update(dict2)
print(dict3)
# {'a': 1, 'c': 3, 'b': 2, 'd': 4}
```
---
## 9. Операции над множествами
----
### Операции над множествами

----
### Объединение (union)
``` python=
# Зададим исходно два множества
a = {'a', 'b'}
b = {'b', 'c'}
c = a | b
# Форма записи объединения
# c = a + b
# Обычное объединение оператором + не работает
# TypeError: unsupported operand type(s) for +: 'set' and 'set'
print(c)
# {'a', 'c', 'b'}
```
----
### Пересечение (intersection)
``` python=
c = a & b
# Форма записи пересечения
print(c) # {'b'}
a = {'a', 'b'}
b = {'b', 'c'}
c = {'b', 'd'}
d = a.intersection(b, c)
# Первый вариант записи
d = set.intersection(a, b, c)
# Второй вариант записи (более наглядный)
print(d) # {'b'}
```
----
### Разница (difference)
Результат зависит от того, какое множество из какого вычитаем
``` python=
c = a - b
print(c) # {'a'}
c = b - a
print(c) # {'c'}
```
----
### Симметричная разница (symmetric_difference)
Это своего рода операция противоположная пересечению -- выбирает элементы из обеих множеств которые не пересекаются, то есть все кроме совпадающих:
``` python=
c = b ^ a
# Форма записи симметричной разницы
print(c)
# {'a', 'c'}
```
----
### Операции сравнения множеств
Операция|Описание
--|--
`A == B` | `True`, если `A` и `B` совпадают
`A != B` | `True`, если `A` и `B` не совпадают
`A <= B` | `True`, если все элементы `A` есть в `B`
`A >= B` | `True`, если все элементы `B` есть в `A`
`A < B` | Эквивалентно `A <= B and A != B`
`A > B` | Эквивалентно `A >= B and A != B`
----
### Примеры
``` python=
set_a = {1, 2, 3}
set_b = {2, 1} # порядок элементов не важен!
set_c = {4}
set_d = {1, 2, 3}
print(set_b < set_a)
# True - set_b целиком входит в set_a
print(set_a >= set_b)
# True - set_b целиком входит в set_a
# При равенстве множеств они одновременно
# и подмножество и надмножество друг для друга
print(set_a == set_d) # True
print(set_a >= set_d) # True
```
---
## 10. Изменение и объединение коллекций
----
### Удаление элементов

----
### Примеры использования оператора del
``` python=
# Работает со списком
my_list = [1, 2, 3, 4, 5, 6, 7]
del my_list[1] # Удаление элемента по индексу
print(my_list) # [1, 3, 4, 5, 6, 7]
del my_list[-3:-1] # Удаление элементов выбранных срезом
print(my_list) # [1, 3, 4, 7]
# del my_list[10]
# IndexError: list assignment index out of range
# Работает со словарем
my_dict = {'a': 1, 'b': 2, 'c': 3}
del my_dict['b']
print(my_dict) # {'a': 1, 'c': 3}
# del my_dict['z']
# KeyError при попытке удалить несуществующий
```
----
### Добавление и обновление элементов

----
### Примеры использования метода .insert(index, element)
``` python=
my_list = [1, 2, 3]
my_list.insert(0, 0) # index = 0 - вставляем в начало
print(my_list) # [0, 1, 2, 3]
my_list.insert(10, 4)
# Индекс выходит за границы списка - просто добавим в конец
print(my_list) # [0, 1, 2, 3, 4]
my_list.insert(-10, -1)
# Индекс выходит за границы в минус - добавим в начало
print(my_list) # [-1, 0, 1, 2, 3, 4]
my_list = [1, 2, 3]
my_list.insert(1, 1.5) # Вставим между 1 и 2, индексация с нуля!
print(my_list) # [1, 1.5, 2, 3]
```
----
### Объединение списков (list)
- Добавляем все элементы второго списка к элементам первого с измением первого списка методом `.extend()`:
``` python=
a.extend(b) # a += b эквивалентно a.extend(b)
print(a, b)
# [1, 2, 3, 4, 5] [4, 5]
```
- Добавляем второй список как один элемент с изменением первого списка методом `.append()`:
``` python=
a.append(b) # a += [b] эквивалентно a.append(b)
print(a, b)
# [1, 2, 3, [4, 5]] [4, 5]
```
----
### Объединение словарей (dict)
- Для изменения словаря с добавления элементов другого словаря используется метод `.update()`
- Обратите внимание: для совпадающих ключей словаря при этом обновляются значения:
``` python=
dict1 = {'a': 1, 'b': 2}
dict2 = {'a': 100, 'c': 3, 'd': 4}
dict1.update(dict2)
print(dict1)
# {'a': 100, 'c': 3, 'b': 2, 'd': 4}
```
<!--
### Изменяемое множество (set)
- Для изменяемого множества (set) кроме обычных операций также возможны их аналоги, но уже с изменением исходного множества
- Эти методы заканчиваются на `_update`
- Результат зависит от того, какое множество каким обновляем
### .difference_update()
``` python=
a = {'a', 'b'}
b = { 'b', 'c'}
a.difference_update(b)
print(a, b)
# {'a'} {'b', 'c'}
a = {'a', 'b'}
b = { 'b', 'c'}
b.difference_update(a)
print(a, b)
# {'a', 'b'} {'c'}
```
### .intersection_update()
``` python=
a = {'a', 'b'}
b = { 'b', 'c'}
a.intersection_update(b)
print(a, b)
# {'b'} {'b', 'c'}
a = {'a', 'b'}
b = { 'b', 'c'}
b.intersection_update(a)
print(a, b)
# {'b', 'a'} {'b'}
```
### .symmetric_difference_update()
``` python=
a = {'a', 'b'}
b = { 'b', 'c'}
a.symmetric_difference_update(b)
print(a, b)
# {'c', 'a'} {'c', 'b'}
a = {'a', 'b'}
b = { 'b', 'c'}
b.symmetric_difference_update(a)
print(a, b)
# {'a', 'b'} {'c', 'a'}
```
-->
---
## Спасибо за внимание!

(c) Яценко Р.Н., 2018-2022
[Учебный центр компьютерных технологий "Кит"](http://kit.kh.ua/)
{"metaMigratedAt":"2023-06-15T15:46:17.908Z","metaMigratedFrom":"YAML","title":"Тема 3. Коллекции","breaks":false,"slideOptions":"{\"allottedMinutes\":180,\"transition\":\"slide\",\"theme\":\"beige\",\"slideNumber\":\"c\",\"spotlight\":{\"enabled\":true}}","description":"© Яценко Р.Н., 2019-2022","contributors":"[{\"id\":\"93a8c43f-1b5b-4461-9101-89b183ccbc1c\",\"add\":30394,\"del\":5829}]"}