{"id":29866468,"url":"https://github.com/yuldashov10/topic_12","last_synced_at":"2025-07-30T12:15:41.644Z","repository":{"id":306890036,"uuid":"1026648092","full_name":"yuldashov10/topic_12","owner":"yuldashov10","description":"12. Работа с множествами","archived":false,"fork":false,"pushed_at":"2025-07-28T07:43:18.000Z","size":1661,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-07-28T09:29:13.258Z","etag":null,"topics":["learning-python","programming","python","python3","shox-py"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yuldashov10.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-07-26T10:13:28.000Z","updated_at":"2025-07-28T07:43:23.000Z","dependencies_parsed_at":"2025-07-28T09:29:15.389Z","dependency_job_id":"b570ab79-44ad-4328-8855-e9d6ce437a24","html_url":"https://github.com/yuldashov10/topic_12","commit_stats":null,"previous_names":["yuldashov10/topic_12"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/yuldashov10/topic_12","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yuldashov10%2Ftopic_12","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yuldashov10%2Ftopic_12/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yuldashov10%2Ftopic_12/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yuldashov10%2Ftopic_12/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yuldashov10","download_url":"https://codeload.github.com/yuldashov10/topic_12/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yuldashov10%2Ftopic_12/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267866700,"owners_count":24157347,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-30T02:00:09.044Z","response_time":70,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["learning-python","programming","python","python3","shox-py"],"created_at":"2025-07-30T12:15:40.843Z","updated_at":"2025-07-30T12:15:41.630Z","avatar_url":"https://github.com/yuldashov10.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 12. Работа с множествами\n\n![img.png](img/cover.svg)\n\n---\n\n## Вступление\n\nДобро пожаловать в тему множества!\n\nВ этой теме мы не просто изучим, как использовать множества в программировании, но и углубимся в математику,\nа именно в раздел **\"Теория множеств\"**. Разберёмся, что такое множество, какие операции с ними бывают, и как\nони помогают нам при решении задач. Помимо базовых операций и методов, мы также познакомимся с неизменяемыми \nмножествами `frozenset()`.\n\n---\n\n## Содержание\n\n- [Теория множеств](#теория-множеств)\n- [Особенности множеств](#особенности-множеств)\n- [Операции над множествами](#операции-над-множествами)\n- [Методы множеств](#методы-множеств)\n- [Неизменяемое множество frozenset()](#неизменяемое-множество-frozenset)\n- [Аннотации типов](#аннотации-типов)\n- [Задания](#задания)\n\n---\n\n## Теория множеств\n\nТеория множеств - это фундаментальный раздел математики, лежащий в основе практически всех математических дисциплин.\nОна формализует понятия *множества* и *элемента*, а также операции и отношения между множествами.\n\n### Основные понятия\n\n1. **Множество**\n\nМножество - это совокупность объектов, объединённых по какому-либо признаку. Например, множество чётных чисел,\nмножество букв алфавита, множество студентов группы или множество геометрических фигур.\n\n![Множество](img/Example_of_a_set.svg)\n\n2. **Элемент множества**\n\nОбъект, входящий в состав множества, называется **элементом**. Например, число `2` является элементом множества\nчётных чисел.\n\n![Элемент множества](img/element_of_set.svg)\n\n3. **Подмножество**\n\nЕсли все элементы множества `B` входят в множество `A`, то `B` называется подмножеством `A`.\n\n![Подмножество](img/subset.svg)\n\n4. **Надмножество**\n\nНадмножество - это множество `A`, которое содержит все элементы другого множества `B`.\nФактически, это просто обратная сторона понятия _подмножества_.\n\n![Подмножество](img/supset.svg)\n\n5. **Пустое множество**\n\nМножество, не содержащее ни одного элемента называется _пустым множеством_ и обозначается символом `∅`.\n\n![Пустое множество](img/empty_set.svg)\n\n6. **Равенство множеств**\n\nДва множества равны, если содержат одни и те же элементы.\n\n![Равенство множеств](img/equality_of_sets.svg)\n\n\u003e Важно: Множество неупорядоченное хранилище и хранит только уникальные элементы, значит проверяется не\n\u003e порядок элементов, а их существование.\n\n---\n\n### Операции над множествами\n\n1. **Объединение**\n\nМножество, содержащее все элементы из двух (или более) исходных множеств.\n\n![Объединение](img/union.svg)\n\n2. **Пересечение**\n\nМножество, включающее только те элементы, которые есть и в `A`, и в `B`.\n\n![Пересечение](img/intersection.svg)\n\n3. **Разность множеств**\n\nМножество, включающее элементы только из `A`, которых нет в `B`.\n\n![Разность](img/difference.svg)\n\n4. **Дополнение**\n\nДополнение множества `A` - это все элементы универсального множества `U`, которых нет в `A`.\n\nПример:\n\n- Пусть `U` - это множество всех людей на планете: `{Аня, Борис, Вика, Глеб, Даша, и т.д.}`\n- А `A` - это множество студентов: `{Аня, Глеб, Даша}`\n\nТогда `A̅` - это множество всех людей, **которые не являются студентами**, то есть `{Борис, Вика, и т.д.}`\n\n![Дополнение](img/complement.svg)\n\nЭти основные операции составляют основу работы с множествами.\nВозникает логичный вопрос: **где на практике применяется теория множеств?**\n\n- В базах данных при выполнении операций `JOIN`, `UNION`, `INTERSECT`\n- В логике и математике при построении формальных моделей и структур\n- В программировании (рассмотрим примеры ниже)\n\n---\n\n## Особенности множеств\n\nМножества в Python - это структура данных, предназначенная для хранения **уникальных** и **неупорядоченных**\nэлементов. Они во многом похожи на математические множества, о которых мы говорили выше, но с рядом особенностей,\nкоторые стоит знать.\n\n**Уникальность элементов**\n\nМножество не может содержать одинаковых значений. Если вы попытаетесь добавить повторяющееся значение - оно просто не\nсохранится. В результате в множестве остаётся только один экземпляр каждого элемента.\n\n```python\nkids: set[str] = {\"Маша\", \"Даша\", \"Аня\", \"Толя\", \"Аня\", \"Петя\", \"Маша\", \"Аня\"}\nprint(kids)  # {'Аня', 'Толя', 'Даша', 'Маша', 'Петя'}\n```\n\n**Неупорядоченность**\n\nМножество не сохраняет порядок элементов, то есть при выводе порядок может быть произвольным и каждый раз отличаться.\n\n```python\ncolours: set[str] = {\n    \"черный\", \"белый\", \"жёлтый\", \"красный\", \"синий\", \"зелёный\"\n}\n\nprint(colours)  # {'черный', 'зелёный', 'жёлтый', 'красный', 'белый', 'синий'}\nprint(colours)  # {'красный', 'зелёный', 'белый', 'синий', 'черный', 'жёлтый'}\n```\n\n**Нельзя изменять элементы**\n\nМножество не поддерживает доступ по индексу или замену элементов напрямую. Это связано с тем, что структура множества\nне хранит позиции элементов, в отличие, например, от списков.\n\n```python\ncolours: set[str] = {\n    \"черный\", \"белый\", \"жёлтый\", \"красный\", \"синий\", \"зелёный\"\n}\n\ncolours[2] = \"оранжевый\"  # TypeError: 'set' object does not support item assignment\n```\n\n**Только хэшируемые (неизменяемые) элементы**\n\nМножества могут хранить только неизменяемые (хэшируемые) типы: числа, строки, кортежи, **но не списки** и др. изменяемые\nтипы. Попытка добавить изменяемый тип в множество приведёт к ошибке `TypeError: unhashable type`.\n\n```python\ndigits_ru: set[tuple[int, str]] = {\n    (1, \"один\"),\n    (2, \"два\"),\n    (3, \"три\"),\n}  # это допустимо\n\ndigits_en: set[list[int | str]] = {\n    [4, \"four\"],\n    [5, \"five\"],\n    [6, \"six\"],\n}  # здесь будет ошибка: TypeError: unhashable type: 'list'\n```\n\n**Создание пустого множества**\n\nЕсли для создания пустых списков и кортежей можно использовать как скобки `[]`, `()`, так и функции `list()`, `tuple()`,\nто с множествами всё чуть иначе. Создать пустое множество можно только с помощью функции `set()`.\n\n\u003e Важно: Запись через `{}` создаёт не множество, а пустой словарь (изучим в следующей теме).\n\n```python\nseen: set[int] = set()\nprint(seen, type(seen))  # set() \u003cclass 'set'\u003e\n\ndata = {}\nprint(data, type(data))  # {} \u003cclass 'dict'\u003e\n```\n\nМножества в Python работают быстро и эффективно. Это отличный инструмент, когда нужно исключить дубликаты или выполнить\nлогические операции вроде объединения, пересечения или разности.\n\n---\n\n## Методы множеств\n\nУ множества также есть собственные методы, которые позволяют выполнять типовые действия: добавление, удаление,\nобновление и др. операции. Ниже рассмотрим каждый из методов более подробно.\n\n---\n\n`set.add()` - добавляет один элемент в множество.\n\nМетод `add()` принимает один аргумент и добавляет его в множество. Если элемент уже существует, он просто игнорируется.\n\n```python\nnames: set[str] = {\"Аня\", \"Глеб\"}\nnames.add(\"Миша\")\nprint(names)  # {'Аня', 'Миша', 'Глеб'}\n\nnames.add(\"Глеб\")\nprint(names)  # {'Миша', 'Глеб', 'Аня'}\n```\n\n---\n\n`set.update()` - добавляет сразу несколько элементов из итерируемого объекта.\n\nРаботает как `add()`, но добавляет **все элементы** из переданной последовательности (списка, кортежа, строки и т.д.).\n\n```python\nnew_data: list[str] = [\"банан\", \"груша\"]\ntropical: tuple[str, ...] = (\"киви\", \"грейпфрут\", \"ананас\")\n\nfruits: set[str] = {\"яблоко\", \"айва\", \"ананас\"}\nfruits.update(new_data)\nprint(fruits)  # {'банан', 'груша', 'ананас', 'яблоко', 'айва'}\n\nfruits.update(tropical)\nprint(fruits)  # {'киви', 'грейпфрут', 'ананас', 'груша', 'яблоко', 'айва', 'банан'}\n\nfruits.update(\"лимон\")\nprint(fruits)  # {'груша', 'л', 'о', 'киви', 'м', 'айва', 'яблоко', 'ананас', 'и', 'банан', 'н', 'грейпфрут'}\n```\n\n---\n\n`set.remove()` - удаляет указанный элемент.\n\nЕсли элемента в множестве нет, то возникнет ошибка `KeyError`.\n\n```python\nanimals: set[str] = {\"тигр\", \"лев\", \"волк\", \"лиса\", \"медведь\"}\n\nanimals.remove(\"лиса\")\nprint(animals)  # {'лев', 'медведь', 'тигр', 'волк'}\n\nanimals.remove(\"кот\")  # KeyError: 'кот'\n```\n\n---\n\n`set.discard()` - безопасно удаляет указанный элемент.\n\nЕсли элемент существует, то он удаляется, в противном случае ничего не происходит и ошибок не будет.\n\n```python\nanimals: set[str] = {\"тигр\", \"лев\", \"волк\", \"лиса\", \"медведь\"}\n\nanimals.discard(\"лиса\")\nprint(animals)  # {'медведь', 'лев', 'тигр', 'волк'}\n\nanimals.discard(\"кот\")\nprint(animals)  # {'медведь', 'лев', 'тигр', 'волк'}\n```\n\n---\n\n`set.pop()` - удаляет произвольный элемент.\n\nВы уже сталкивались с методом `list.pop()` у списков, метод удалял последний элемент и возвращал его. Так как\nмножества неупорядоченные, нельзя заранее знать какой элемент будет удалён. Если множество пустое возникнет `KeyError`.\n\n```python\nemoji: set[str] = {\"🎲\", \"🎯\", \"🧩\", \"🎳\"}\n\nfirst: str = emoji.pop()\nprint(first)  # 🧩\nprint(emoji)  # {'🎳', '🎲', '🎯'}\n\nsecond: str = emoji.pop()\nthird: str = emoji.pop()\nfourth: str = emoji.pop()\nprint(emoji)  # set()\n\nfifth: str = emoji.pop()  # KeyError: 'pop from an empty set'\n```\n\n---\n\n`set.clear()` - полностью очищает множество.\n\nРаботает как у списков, после вызова метода множество становится пустым.\n\n```python\nemoji: set[str] = {\"🎲\", \"🎯\", \"🧩\", \"🎳\"}\n\nemoji.clear()\nprint(emoji)  # set()\n```\n\n---\n\n`set.copy()` - создаёт поверхностную копию множества.\n\nТакже работает как у списков, позволяет работать с копией объекта, не изменяя оригинал.\n\n```python\ntransports: set[str] = {\"автобус\", \"автомобиль\", \"электромобиль\"}\n\ntemp_transports: set[str] = transports.copy()\ntemp_transports.add(\"трактор\")\n\nprint(transports)  # {'электромобиль', 'автобус', 'автомобиль'}\nprint(temp_transports)  # {'автомобиль', 'автобус', 'трактор', 'электромобиль'}\n```\n\n---\n\nДалее рассмотрим методы, основанные на классических операциях из теории множеств.\n\n`set_a.union(set_b)` - объединяет множества.\n\nВозвращает новое множество, содержащее все элементы из обоих множеств. Вместо метода можно использовать оператор `|`,\nрезультат будет идентичным. Однако предпочтительнее использовать методы, они явно отражают смысл выполняемой операции\nи повышают читаемость кода.\n\n```python\na: set[int] = {1, 2, 3, 4}\nb: set[int] = {3, 4, 5, 6}\n\nres_1: set[int] = a.union(b)\nres_2: set[int] = a | b\n\nprint(res_1)  # {1, 2, 3, 4, 5, 6}\nprint(res_2)  # {1, 2, 3, 4, 5, 6}\n```\n\n---\n\n`set_a.intersection(set_b)` - возвращает пересечение множеств.\n\nВозвращает новое множество, содержащее только общие элементы. Альтернативно можно использовать оператор `\u0026`\nвместо метода.\n\n```python\na: set[int] = {1, 2, 3, 4}\nb: set[int] = {3, 4, 5, 6}\n\nres_1: set[int] = a.intersection(b)\nres_2: set[int] = a \u0026 b\n\nprint(res_1)  # {3, 4}\nprint(res_2)  # {3, 4}\n```\n\n---\n\n`set_a.difference(set_b)` - возвращает разность множеств.\n\nВозвращает новое множество из элементов, присутствующих в `set_a`, но отсутствующих в `set_b`.\nАналогичная операция возможна с помощью оператора `-`.\n\n```python\na: set[int] = {1, 2, 3, 4}\nb: set[int] = {3, 4, 5, 6}\n\nres_1: set[int] = a.difference(b)\nres_2: set[int] = a - b\n\nprint(res_1)  # {1, 2}\nprint(res_2)  # {1, 2}\n```\n\n---\n\n`set_a.symmetric_difference(set_b)` - симметрическая разность множеств.\n\nВозвращает элементы, которые входят только в одно из двух множеств, исключая общие. То же самое можно сделать с\nпомощью оператора `^`.\n\n```python\na: set[int] = {1, 2, 3, 4}\nb: set[int] = {3, 4, 5, 6}\n\nres_1: set[int] = a.symmetric_difference(b)\nres_2: set[int] = a ^ b\n\nprint(res_1)  # {1, 2, 5, 6}\nprint(res_2)  # {1, 2, 5, 6}\n```\n\n---\n\nСледующие методы возвращают логическое значение `True` или `False`, отвечая на конкретные вопросы о взаимосвязи\nмножеств.\n\n`set_b.issubset(set_a)` - проверяет, является ли подмножеством.\n\nВозвращает `True`, если все элементы `set_b` содержатся в `set_a`, в противном случае `False`.\n\n```python\na: set[int] = {1, 5, 7, 9, 2}\nb: set[int] = {1, 9}\n\nprint(b.issubset(a))  # True\nprint(a.issubset(b))  # False\n```\n\n---\n\n`set_a.issuperset(set_b)` - проверяет, является ли надмножеством.\n\nВозвращает `True`, если множество `set_a` содержит все элементы `set_b`, в противном случае `False`.\n\n```python\na: set[int] = {1, 5, 7, 9, 2}\nb: set[int] = {1, 9}\n\nprint(a.issuperset(b))  # True\nprint(b.issuperset(a))  # False\n```\n\n---\n\n`set_a.isdisjoint(set_b)` - проверяет, есть ли общие элементы у множеств.\n\nЕсли нет ни одного общего элемента возвращает `True`, в противном случае `False`. Удобно использовать при проверке\nпересекаются ли множества.\n\n```python\na: set[int] = {1, 2, 3, 4}\nb: set[int] = {3, 4, 5, 6}\nc: set[int] = {7, 8, 9}\n\nprint(a.isdisjoint(b))  # False\nprint(a.isdisjoint(c))  # True\nprint(b.isdisjoint(c))  # True\n```\n\nКак видно, некоторые методы множеств работают похоже на методы списков. Тем не менее, у них есть и своя специфика,\nпривыкание к ним и уверенное использование приходит с практикой. Далее рассмотрим неизменяемый тип\nмножества `frozenset()`.\n\n---\n\n## Неизменяемое множество `frozenset()`\n\nПомимо изменяемого типа множества `set()`, в Python есть его неизменяемый аналог `frozenset()`. Его можно сравнить\nс отношением `tuple()` к `list()` так же, как кортеж нельзя изменить после создания, множество `frozenset()` остаётся\nнеизменным после инициализации.\n\n**Создание `frozenset()`**\n\nСоздать `frozenset` можно исключительно с помощью функции `frozenset()` и после создания множество становится\nполностью неизменяемым.\n\n```python\ndata: list[int] = [10, 20, 30, 40]\nnumbers: frozenset[int] = frozenset(data)\nprint(numbers)  # frozenset({40, 10, 20, 30})\n\nusernames: tuple[str, ...] = (\"admin\", \"moder\", \"root\", \"systemBoss\")\nsafe_data: frozenset[str] = frozenset(usernames)\nprint(safe_data)  # frozenset({'moder', 'systemBoss', 'admin', 'root'})\n```\n\n\u003e - Пустое множество `frozenset()` создать можно, но на практике это редко имеет смысл, так как основная ценность\n    `frozenset` это хранение безопасных и неизменяемых данных, и пустое множество в этом контексте обычно\n    не используется.\n\u003e - `frozenset()` можно использовать как ключ в словаре или элемент другого множества, поскольку он хешируемый и\n    неизменяемый тип.\n\n---\n\n### Методы `frozenset()`\n\n`frozenset()` поддерживает некоторые операции и методы, которые есть у `set()`, за исключением методов изменяющих\nмножество.\n\n`frozenset_a.union(frozenset_b)` - объединяет множества.\n\nВозвращает новое `frozenset`, которое содержит все элементы из `frozenset_a` и `frozenset_b`множества (удаляя\nдубликаты). Аналогично можно использовать оператор `|`.\n\n```python\na: frozenset[int] = frozenset({10, 20, 30})\nb: frozenset[int] = frozenset({30, 40, 50})\n\nres_1: frozenset[int] = a.union(b)\nres_2: frozenset[int] = a | b\n\nprint(res_1)  # frozenset({50, 20, 40, 10, 30})\nprint(res_2)  # frozenset({50, 20, 40, 10, 30})\n```\n\n---\n\n`frozenset_a.intersection(frozenset_b)` - возвращает пересечение множеств.\n\nВозвращает новое `frozenset`, содержащее только общие элементы из двух множеств. Также можно использовать оператор `\u0026`.\n\n```python\na: frozenset[int] = frozenset({10, 20, 30, 40})\nb: frozenset[int] = frozenset({30, 40, 50})\n\nres_1: frozenset[int] = a.intersection(b)\nres_2: frozenset[int] = a \u0026 b\n\nprint(res_1)  # frozenset({40, 30})\nprint(res_2)  # frozenset({40, 30})\n```\n\n---\n\n`frozenset_a.difference(frozenset_b)` - возвращает разность множеств.\n\nВозвращает новое `frozenset` из элементов множества `frozenset_a`, отсутствующих в `frozenset_b`. Можно также\nиспользовать оператор `-`.\n\n```python\na: frozenset[int] = frozenset({10, 20, 30, 40})\nb: frozenset[int] = frozenset({30, 40, 50})\n\nres_1: frozenset[int] = a.difference(b)\nres_2: frozenset[int] = a - b\n\nprint(res_1)  # frozenset({10, 20})\nprint(res_2)  # frozenset({10, 20})\n```\n\n`frozenset_a.symmetric_difference(frozenset_b)` - симметрическая разность множеств.\n\nВозвращает новое `frozenset`, состоящее из элементов, которые есть только в одном из двух множеств, исключая общие.\nАналогично можно использовать оператор `^`.\n\n---\n\nКроме того, у `frozenset` есть следующие методы, которые работают так же, как у `set()`:\n\n- `frozenset_b.issubset(frozenset_a)` - проверяет, является ли `frozenset_b` подмножеством `frozenset_a`.\n  Возвращает `True`, если все элементы `frozenset_b` содержатся в `frozenset_a`, иначе `False`.\n- `frozenset_a.issuperset(frozenset_b)` - проверяет, является ли `frozenset_a` надмножеством `frozenset_b`.\n  Возвращает `True`, если `frozenset_a` содержит все элементы `frozenset_b`, иначе `False`.\n- `frozenset_a.isdisjoint(frozenset_b)` - проверяет, пересекаются ли множества `frozenset_a` и `frozenset_b`.\n  Возвращает `True`, если множества не имеют общих элементов, иначе `False`.\n\n\u003e Важно: у `frozenset` отсутствуют методы изменения множества: `add()`, `remove()`, `pop()`, `clear()` и `update()`,\n\u003e поскольку множество неизменяемое.\n\n---\n\n**Где используется `frozenset()`?**\n\n`frozenset` полезен, когда необходимо хранить множество данных в неизменяемом виде, например:\n\n- Когда важно гарантировать, что множество не будет случайно изменено в процессе работы программы.\n- Для повышения безопасности и стабильности данных в сложных структурах.\n- В качестве ключей словарей или элементов других множеств, так как `set` является изменяемым и не может использоваться\n  для этих целей.\n\n### Таблица 12.1: Сравнение `set()` и `frozenset()`\n\n| Особенность                                      | `set()`           | `frozenset()`           |\n|--------------------------------------------------|-------------------|-------------------------|\n| Изменяемость                                     | Да                | Нет                     |\n| Хешируемость                                     | Нет               | Да                      |\n| Можно использовать как ключ словаря              | Нет               | Да                      |\n| Можно использовать как элемент другого множества | Нет               | Да                      |\n| Создание                                         | `set([iterable])` | `frozenset([iterable])` |\n\n`frozenset()` дополняет стандартный `set()` и расширяет возможности по работе с коллекциями и безопасностью данных. В\nповседневном программировании `frozenset()` встречается реже, чем `set()`, но в определённых случаях он незаменим.\n\n---\n\n## Аннотации типов\n\nКак уже обсуждали в предыдущих темах аннотация типов это хорошая практика, повышает читаемость и надёжность кода.\nКак помните в старых версиях Python (до версии 3.9) для аннотирования сложных типов необходимо было импортировать\nтипы из модуля `typing`. А начиная с версии 3.9 можно использовать встроенный синтаксис Python без\nдополнительных импортов.\n\n- **Подход до версии 3.9**:\n\nДля `set`:\n\n```python\nfrom typing import Set\n\nusernames: Set[str] = {\"admin\", \"moder\", \"root\", \"systemBoss\"}\npoints: Set[float] = {3.14, 6.28, 2.78, .546}\ndigits: Set[int] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}\nstates: Set[bool] = {True, False}\n\nprint(usernames)  # {'root', 'moder', 'systemBoss', 'admin'}\nprint(points)  # {3.14, 0.546, 2.78, 6.28}\nprint(digits)  # {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}\nprint(states)  # {False, True}\n```\n\n- Для `frozenset`:\n\n```python\nfrom typing import FrozenSet\n\nusernames: FrozenSet[str] = frozenset({\"admin\", \"moder\", \"root\", \"systemBoss\"})\npoints: FrozenSet[float] = frozenset({3.14, 6.28, 2.78, .546})\ndigits: FrozenSet[int] = frozenset([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])\nstates: FrozenSet[bool] = frozenset((True, False))\n\nprint(usernames)  # frozenset({'systemBoss', 'root', 'admin', 'moder'})\nprint(points)  # frozenset({0.546, 2.78, 3.14, 6.28})\nprint(digits)  # frozenset({0, 1, 2, 3, 4, 5, 6, 7, 8, 9})\nprint(states)  # frozenset({False, True})\n```\n\n- **Подход начиная с версии 3.9**:\n\nДля `set`:\n\n```python\nusernames: set[str] = {\"admin\", \"moder\", \"root\", \"systemBoss\"}\npoints: set[float] = {3.14, 6.28, 2.78, .546}\ndigits: set[int] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}\nstates: set[bool] = {True, False}\n\nprint(usernames)  # {'moder', 'systemBoss', 'admin', 'root'}\nprint(points)  # {2.78, 0.546, 3.14, 6.28}\nprint(digits)  # {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}\nprint(states)  # {False, True}\n```\n\n- Для `frozenset`:\n\n```python\nusernames: frozenset[str] = frozenset({\"admin\", \"moder\", \"root\", \"systemBoss\"})\npoints: frozenset[float] = frozenset({3.14, 6.28, 2.78, .546})\ndigits: frozenset[int] = frozenset([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])\nstates: frozenset[bool] = frozenset((True, False))\n\nprint(usernames)  # frozenset({'root', 'systemBoss', 'admin', 'moder'})\nprint(points)  # frozenset({0.546, 2.78, 3.14, 6.28})\nprint(digits)  # frozenset({0, 1, 2, 3, 4, 5, 6, 7, 8, 9})\nprint(states)  # frozenset({False, True})\n```\n\nЕсли в множествах хранятся сложные типы, например кортежи координат, типы можно указывать так:\n\n```python\nfrom typing import Tuple, Set, FrozenSet\n\n# До 3.9\ncoordinates: Set[Tuple[int, int]] = {(0, 0), (1, 2), (3, 4)}\ncoordinates_2: FrozenSet[Tuple[int, int]] = frozenset({(0, 0), (1, 2), (3, 4)})\n\n# С 3.9\ncoordinates: set[tuple[int, int]] = {(0, 0), (1, 2), (3, 4)}\ncoordinates_2: frozenset[tuple[int, int]] = frozenset({(0, 0), (1, 2), (3, 4)})\n```\n\nИспользуйте аннотации типов, точно не пожалеете. Они помогают быстрее разобраться в коде и вам, и тем,\nкто будет читать ваш код.\n\n---\n\n## Заключение\n\nМы с вами изучили ещё один встроенный тип данных Python, и как видите, множества тесно связаны с математической теорией\nмножеств. Чтобы лучше понять тему, стоит немного освежить знания по теории множеств. Ниже в полезных ссылках будет\nметодичка из первой лекции университета, в которой собраны основные понятия и термины с простыми примерами.\n\nКак только вы хорошо разберётесь в теории, смело переходите к практике, ведь работа с множествами требует прочного\nпонимания их сути. В следующей теме мы обсудим крайний встроенный тип данных **словари**.\n\n---\n\n## [Задания](./tasks/TASKS.md)\n\nПрактические задания для самостоятельной работы.\n\n- Постарайтесь использовать только те знания, которые были изучены в пройденных темах.\n  Не стоит использовать конструкции, которые мы ещё не разбирали.\n- Убедитесь, что удалили все лишние комментарии из вашего кода.\n- Постарайтесь указывать аннотации типов для переменных.\n- Рекомендуем решить все задания самостоятельно.\n\nЕсли возникнут трудности, не стесняйтесь обратиться за помощью в наш [Телеграм-чат](https://t.me/shox_py_discuss).\nЧтобы перейти к заданиям, кликните на заголовок **Задания** или нажмите [сюда](./tasks/TASKS.md).\n\n---\n\n## Полезные ссылки\n\n- [Telegram: Лекция №1. Основные понятия теории множеств](https://t.me/shox_py_discuss/36/94)\n\n---\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyuldashov10%2Ftopic_12","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyuldashov10%2Ftopic_12","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyuldashov10%2Ftopic_12/lists"}