Множества
Множества в отличие от списков и кортежей могут хранить объекты только неизменяемого типа данных, например, числа или строки. Также они обладают двумя ключевыми особенностями: неупорядоченностью и уникальностью. К элементам множества нельзя обратиться по индексу, так как они не хранятся в каком-либо определенном порядке, а также множества игнорируют повторяющиеся элементы, оставляя только уникальные значения.
При этом множества изменяемы, поэтому большинство их методов изменяют исходное множество и возвращают None.
Создание множества
Существует несколько способов создания множеств в Python.
Фигурные скобки для создания множества
Множество создаёт перечисление элементов через запятую внутри фигурных скобок:
berries = {"Рябина", "Черёмуха", "Земляника"}
Функция set() для создания множества
Любую встроенную коллекцию можно преобразовать в множество с помощью функции set().
|
Функция |
|
|
Описание |
Создаёт множество из всех элементов коллекции |
|
Параметры |
|
|
Возвращаемое значение |
Множество |
Такое множество будет содержать все уникальные элементы этой коллекции, а повторяющиеся элементы будут проигнорированы:
numbers = [1, 2, 2, 3, 3, 3]
print(set(numbers))
# Вывод: {1, 2, 3}
Так же как функция list() разбивает строку на список символов, так и функция set() разбивает строку на множество символов:
plant = "Кукуруза"
print(set(plant))
# Вывод: {'К', 'р', 'а', 'у', 'з', 'к'}
Так как элементы в множестве не упорядочены, то их порядок может отличаться при каждом запуске программы:
food = ("Хлеб", "Масло", "Хлеб", "Масло", "Джем")
food_set = set(food)
print(food_set)
# Вывод (возможный): {'Хлеб', 'Масло', 'Джем'}
# Вывод (возможный): {Масло, 'Хлеб', 'Джем'}
Создание пустого множества
Пустое множество создаёт функция set() без аргументов:
menu = set()
Однако пустые фигурные скобки создают пустой словарь, а не множество:
menu = {}
print(type(menu))
# Вывод: <class 'dict'>
Добавление элемента в множество
Метод set.add() добавляет один элемент в множество. При этом следует помнить о том, что множества хранят только уникальные значения.
|
Метод |
|
|
Описание |
Добавляет в множество |
|
Параметры |
|
|
Возвращаемое значение |
|
Элемент будет добавлен только, если он отсутствует в множестве, иначе множество останется неизменным:
transport = {"Автобус", "Трамвай", "Такси"}
transport.add("Метро")
print(transport)
# Вывод: {'Метро', 'Автобус', 'Такси', 'Трамвай'}
transport.add("Автобус")
print(transport)
# Вывод: {'Метро', 'Автобус', 'Такси', 'Трамвай'}
Но если нужно добавить сразу несколько элементов, то на помощь приходит метод set.update().
|
Метод |
|
|
Описание |
Добавляет в множество |
|
Параметры |
|
|
Возвращаемое значение |
|
Параметр *iterable означает, что мы можем передать данному методу несколько коллекций, перечислив их через запятую. Поэтому в существующее множество мы можем как все элементы одного списка:
weather = {"Мокрый снег", "Град", "Дождь"}
rain = ["Дождь", "Морось", "Ливень"]
weather.update(rain)
print(weather)
# Вывод: {'Мокрый снег', 'Град', 'Дождь', 'Ливень', 'Морось'}
Так и одновременно все элементы кортежа и значения словаря:
weather = {"Ясно", "Пасмурно", "Переменная облачность"}
wind = ("Слабый ветер", "Умеренный ветер")
temperature = {30: "Жарко", 21: "Комфортно", -40: "Холодно"}
weather.update(wind, temperature.values())
print(weather)
# Вывод: {'Ясно', 'Холодно', 'Комфортно', 'Переменная облачность', 'Жарко', 'Умеренный ветер', 'Слабый ветер', 'Пасмурно'}
Удаление элементов из множества
Из множества можно удалить элемент по значению, а также удалить случайный элемент. Кроме этого, можно полностью очистить множество, удалив все его элементы.
Удаление элемента из множества по значению
Для удаления из множества элемента по его значению существует два метода – set.remove() и set.discord(). Ключевое различие между этими двумя методами заключается в их поведении, когда элемент в множестве не найден:
- метод
set.remove()в таком случае вызовет исключениеKeyError, что приведёт к прерыванию выполнения программы; - метод
set.discard()просто ничего не делает.
|
Методы |
|
|
Описание |
Удаляют объект |
|
Параметры |
|
|
Возвращаемое значение |
|
Например, используем метод set.remove() и удалим число 1 из следующего множества:
numbers = {1, 2, 3, "один", "два", "три"}
numbers.remove(1)
print(numbers)
# Вывод: {2, 3, 'один', 'три', 'два'}
Однако если мы попробуем удалить элемент, которого нет в множестве, то будет вызвано исключение KeyError:
numbers.remove("пять")
print(numbers)
# Ошибка: KeyError: 'пять'
В таком случае следует использовать метод set.discard(), который перед удалением проверяет наличие элемента в множестве:
numbers.discard("пять")
print(numbers)
# Вывод: {2, 3, 'один', 'три', 'два'}
Так как элемент "пять" отсутствует в множестве, то исходное множество остаётся неизменным.
Удаление случайного элемента множества
Для удаления (и возвращения) случайного элемента множества предназначен метод set.pop().
|
Методы |
|
|
Описание |
Удаляет и возвращает случайный элемент множества |
|
Возвращаемое значение |
Удаляемый элемент |
Как и метод списков list.pop(), данный метод не просто удаляет элемент, а возвращает его:
mail = {"mail.ru", "yandex.ru", "gmail.com"}
deleted_mail = mail.pop()
print(f"Удалённый элемент - {deleted_mail}")
# Вывод: Удалённый элемент - gmail.com
Удаление всех элементов множества
Также можно полностью очистить множество, используя метод set.clear().
|
Метод |
|
|
Описание |
Удаляет все элементы множества |
|
Возвращаемое значение |
None |
В таком случае множество станет пустым:
video = {"rutube", "youtube"}
video.clear()
print(video)
# Вывод: {}
Замороженные множества
Кроме обычных множеств, которые изменяемы, в Python также представлена их неизменяемая версия, создаваемая функцией frozenset().
|
Функция |
|
|
Описание |
Создаёт замороженное (неизменяемое) множество из всех элементов коллекции |
|
Параметры |
|
|
Возвращаемое значение |
Замороженное (неизменяемое) множество |
Как и в обычное множество (set), в замороженное множество (frozenset) можно преобразовать любую коллекцию:
frozen_numbers = frozenset([1, 2, 3, 3, 2])
print(frozen_numbers)
# Вывод: frozenset({1, 2, 3})
Такие множества обладает всеми свойствами множеств, но не поддерживает методы, изменяющие содержимое, например, set.remove() или set.add():
frozen_numbers = frozenset([1, 2, 3, 3, 2])
frozen_numbers.add(4)
# Ошибка: AttributeError: 'frozenset' object has no attribute 'add'
Благодаря неизменяемости замороженных множеств они могут быть использованы в качестве ключей словаря или элементов другого множества.
Например, элементом множества не может быть список, так он изменяем, однако его можно преобразовать в замороженное множество:
numbers = {1, 2, 3, 4, 5}
big_numbers = [100000, 100001, 100002]
frozen_big_numbers = frozenset(big_numbers)
numbers.add(frozen_big_numbers)
print(numbers)
# Вывод: {1, 2, 3, 4, 5, frozenset({100000, 100001, 100002})}
Примеры
Пример 1. Нормализация тегов
Платформа для ведения блога обеспечивает уникальность тегов и единообразие их написания (в нижнем регистре):
raw_tags = ["Python", "python", "Алгоритмы", "базы данных", "Базы Данных"]
normalized_tags = set() # Пустое множество для обработанных тегов
# Нормализация тегов
for tag in raw_tags:
normalized_tags.add(tag.lower())
print("Уникальные теги:", normalized_tags)
Вывод:
Уникальные теги: {'алгоритмы', 'python', 'базы данных'}
Пример 2. Управление активными сессиями пользователей
Программа отслеживает уникальные IP-адреса, с которых пользователи в настоящее время подключены к сервису. Это критично для мониторинга нагрузки, обнаружения аномалий и защиты от DDoS-атак. При успешной авторизации нового пользователя, его IP-адрес безопасно добавляется в множество, хранящее все активные IP-адреса. Также реализуется возможность добавления сразу нескольких IP-адресов. Когда пользователь выходит или его сессия истекает, его IP-адрес удаляется:
active_ips = {"10.0.0.5", "172.16.0.1"}
# Добавление одного IP
active_ips.add("192.168.1.1")
# Добавление нескольких IP
new_batch = {"10.0.0.2", "192.168.1.5"}
active_ips.update(new_batch)
print(f"Подключенные IP-адреса: {active_ips}")
# Несколько IP-адресов отключаются
disconnected_ips = ["10.0.0.5", "192.168.1.99"]
print(f"Отключаем адреса {disconnected_ips}...")
active_ips.discard("10.0.0.5") # Удаление существующего IP
active_ips.discard("192.168.1.99") # Игнорирование несуществующего IP
print(f"Подключенные IP-адреса: {active_ips}")
Вывод:
Подключенные IP-адреса: {'192.168.1.5', '10.0.0.2', '10.0.0.5', '172.16.0.1', '192.168.1.1'}
Отключаем адреса ['10.0.0.5', '192.168.1.99']...
Подключенные IP-адреса: {'192.168.1.5', '10.0.0.2', '172.16.0.1', '192.168.1.1'}
Пример 3. Очистка диспетчера задач
Определённые события в системе имеют одинаковый приоритет, поэтому при для их обработки программа берёт случайное событие из множества событий, после чего удаляет его. В конце работы программа очищает всё множество событий:
pending_events = {"Ошибка базы", "Новое подключение", "Сбой авторизации",
"Предупреждение о нагрузке"}
# Обрабатка случайного события
processed_event = pending_events.pop()
print(f"Обработано событие: '{processed_event}'")
print(f"Остались события: {pending_events}", end="\n---------\n")
# Обработка ещё одного случайного события
processed_event = pending_events.pop()
print(f"Обработано событие: '{processed_event}'")
print(f"Остались события: {pending_events}", end="\n---------\n")
# В конце работы очищаем всё
pending_events.clear()
print(f"События в конце работы: {pending_events}")
Вывод:
Обработано событие: 'Новое подключение'
Остались события: {'Ошибка базы', 'Предупреждение о нагрузке', 'Сбой авторизации'}
---------
Обработано событие: 'Ошибка базы'
Остались события: {'Предупреждение о нагрузке', 'Сбой авторизации'}
---------
События в конце работы: set()
Итоги
- Функция
set()преобразует другую коллекцию в множество. - Множества изменяемы, но их элементами могут быть только объекты неизменяемого типа данных.
- Все элементы в множестве уникальны, а повторяющиеся значения игнорируются.
- Элементы множества не упорядочены и к ним нельзя обратиться напрямую.
- Функция
frozenset()преобразует другую коллекцию в замороженное (неизменяемое) множество.
|
Метод |
Описание |
|---|---|
|
|
Добавляет в множество |
|
|
Добавляет в множество |
|
|
Удаляет объект |
|
|
Удаляет объект |
|
|
Удаляет и возвращает случайный элемент множества |
|
|
Удаляет все элементы множества |
Задания для самопроверки
1. Чем множества отличаются от списков и кортежей?
Множества не упорядочены и содержат только уникальные значения.
2. Дан список duplicates = [1, 2, 2, 3, 4, 4, 5, 5, 5]. Преобразуйте этот список в множество для удаления дубликатов, а затем снова преобразуйте полученное множество в список и выведите его на экран.
duplicates = [1, 2, 2, 3, 4, 4, 5, 5, 5]
lst = list(set(duplicates))
print(lst)
# Вывод: [1, 2, 3, 4, 5]
3. Создайте пустое множество empty_set, добавьте в него элементы 10 и 20 и выведите полученное множество на экран.
empty_set = set()
empty_set.add(10)
empty_set.add(20)
print(empty_set)
# Вывод: {10, 20}
4. Дано множество tasks = {"Работа", "Учеба", "Сон", "Спорт"}. Удалите случайный элемент множества, присвойте его переменной completed_task и выведите значение этой переменной на экран.
tasks = {"Работа", "Учеба", "Сон", "Спорт"}
completed_task = tasks.pop()
print(completed_task)
# Вывод: Спорт
5. Дан список languages = ["Python", "JavaScript", "C++", "Python"]. Создайте из этого списка неизменяемое множество и выведите его на экран. Можете ли вы добавить в него новый элемент "Go"? Почему?
languages = ["Python", "JavaScript", "C++", "Python"]
frozen_languages = frozenset(languages)
print(frozen_languages)
# Вывод: frozenset({'JavaScript', 'C++', 'Python'})
0 комментариев