Перейти к содержанию

412 уроков, 25 библиотек и челлендж «Что выведет код?» — бесплатно, код прямо в браузере

Начать обучение
Урок 3 из 20 Начальный 15 мин 100 XP

add и update в Python: добавление элементов в set

Множество собрано — теперь пополняем: add кладёт один элемент, update принимает списки, множества и даже строки. Дубликаты исчезают тихо, без ошибок.

Редакция Питоники

Созданное множество — не приговор: оно изменяемое, и элементы в него добавляют всю жизнь программы. У этой операции два глагола: add для одиночного значения и update для целой пачки. Разница кажется мелкой, но у update спрятаны две ловушки — строки разбираются на буквы, а возвращаемое значение у обоих методов отсутствует. Разберём всё на живом коде.

add: один элемент

Метод add принимает один аргумент и кладёт его в множество. Наполним теги статьи по одному:

наполняем множество по одному
tags = {'python'}
tags.add('code')
tags.add('datetime')
print(sorted(tags))
print(len(tags))
Вывод
['code', 'datetime', 'python']
3

Каждый вызов add вырос множество на один элемент. Заметьте: add меняет множество на месте — его не нужно присваивать, теги после вызова уже новые. Напечатать по-прежнему честнее через sorted: порядок внутри set не гарантирован.

Дубликат тихо игнорируется

Что произойдёт, если добавить элемент, который уже есть? Ничего — и это не сбой, а дизайнерское решение: уникальность встроена в структуру:

повторный add ничего не меняет
tags = {'python', 'code'}
before = len(tags)
tags.add('python')
after = len(tags)
print('было:', before, '- стало:', after)
print(sorted(tags))
Вывод
было: 2 - стало: 2
['code', 'python']

Никакой ошибки, никакого изменения длины — повтор просто не пустили внутрь. Та же тишина и у update: он вольёт новый набор, и дубликаты из него растворятся на границе множества:

update тоже не пустит дубль
base = {1, 2}
base.update([2, 3, 2])
print(sorted(base))
print(len(base))
Вывод
[1, 2, 3]
3

Из трёх значений списка в множество попали два новых: повторная двойка исчезла. Писать проверку есть ли элемент перед add не нужно — множество само решает, пускать ли повтор.

update: пачка элементов

add умеет один элемент. Когда приходит целая поставка — список тегов, результаты запроса, другой журнал — вызывать add в цикле не нужно: метод update принимает набор целиком:

update вливает список
tags = {'python'}
tags.update(['code', 'datetime'])
print(sorted(tags))
print(len(tags))
Вывод
['code', 'datetime', 'python']
3

Два элемента списка легли в множество одним вызовом. У update есть ещё одна суперсила: он принимает сразу несколько аргументов и вольёт их все — списки, множества, что угодно перебираемое:

update из списка и множества разом
base = {1, 2}
base.update([3, 4], {5})
print(sorted(base))
Вывод
[1, 2, 3, 4, 5]

Один вызов, два источника, пять элементов: список и литеральное множество влились за раз. Именно поэтому update — не пара к add, а отдельный инструмент: он про источники, а не про элементы.

Ловушка: update от строки

Строка — перебираемая величина: по ней можно идти циклом. Значит, update её примет — но добавит не строку, а её буквы по одной. Это классическая ловушка новичка:

update от строки добавляет буквы
letters = {'x'}
letters.update('abc')
print(sorted(letters))
Вывод
['a', 'b', 'c', 'x']

В множество легли три буквы: a, b, c — по символу из строки. Если нужна строка целиком, как один элемент, используют add: add('abc') положил бы единственное значение 'abc'. Правило различения простое: add кладёт аргумент как есть, update разбирает аргумент на элементы.

Списки, множества и строки update принимает; а вот число перебрать нельзя — update, как и set(), требует перебираемое. Попытка скормить ему число падает прямо на месте:

update от числа падает
tags = {'python'}
tags.update(42)
Вывод
Traceback (most recent call last):
  File "app.py", line 2, in <module>
    tags.update(42)
    ~~~~~~~~~~~^^^^
TypeError: 'int' object is not iterable
Программа падает на вызове update: число нельзя перебрать. Путь к файлу в traceback будет вашим (показан условный app.py).

Сообщение то же, что у set(42) из прошлого урока: объект не перебирается. Число добавляют через add — оно элемент, а не набор.

add и update ничего не возвращают

Оба метода меняют множество на месте и возвращают None — никакое. Это чужой для списков текст: append у списка ведёт себя точно так же, но рука всё равно тянется написать присваивание. Посмотрим, что вернёт add:

что вернул add
s = {1}
result = s.add(2)
print(result)
print(sorted(s))
Вывод
None
[1, 2]

Элемент добавился, а result — None: метод отработал внутри множества и вернул пустоту. Отсюда главная ошибка темы: s = s.add(2) записывает в s значение None, и множество теряется — все элементы исчезают вместе с именем. Методы, меняющие объект на месте, не возвращают этот объект: они уже всё сделали.

Шпаргалка: add и update

Два метода, два масштаба. Таблица помогает выбрать за секунду:

ВызовЧто делаетПример результата
s.add('abc')Кладёт строку как один элемент{'abc'}
s.update('abc')Разбирает строку на буквы{'a', 'b', 'c'}
s.update([1, 2], {3})Вливает все наборы разом{1, 2, 3}
s.update(42)Падает: число не перебираетсяTypeError
s = s.add(1)Теряет множество: add вернул Nones становится None

Пополнять множество научились — один элемент и пачками. Обратная операция не менее важна: убрать элемент можно тремя способами, и один из них падает на отсутствующем значении. Об этом — урок про remove, discard и pop.

Что выведет код?

Сначала предскажи ответ в голове — это главный навык программиста.

s = {2}
s.add(1)
s.add(2)
print(len(s))
print(sorted(s))
tags = {'web'}
tags.update(['py', 'web'])
tags.update('go')
print(sorted(tags))
s = {1, 2}
result = s.add(3)
print(result)
print(sorted(s))
Проверь себя
0 / 6

1. Что произойдёт при tags.add('python'), если 'python' уже в множестве?

2. Чем update отличается от add?

3. Что сделает tags.update('ab')?

4. Что возвращает метод add?

5. Сколько элементов будет в s после s = {1}; s.update([2, 2, 3])?

6. Как добавить строку 'code' в множество как один элемент?

Карточки терминов
Запомнено: 0 / 7
Практика

Начните с tags = {'python'}. Добавьте 'code' через add, затем влейте ['sql', 'python'] через update. Напечатайте отсортированный список тегов и их количество.

practice.py
Вопросы и ответы по уроку

Как добавить элемент в множество Python?

Методом add: tags.add('code') кладёт один элемент. Дубликат при этом молча игнорируется — проверка перед добавлением не нужна. Для пачки элементов используйте update со списком, множеством или строкой.

Урок 2: создание множеств

Чем update отличается от add?

add принимает ровно один элемент и кладёт его как есть. update принимает любое количество перебираемых наборов и вливает их элементы: update([1, 2], {3}) добавит три значения. Строка у update разбирается на буквы — для строки целиком нужен add.

Почему add не добавляет дубликат и не ругается?

Уникальность — свойство самой структуры: множество вычисляет хеш элемента и не хранит два одинаковых. Повтор — не исключительная ситуация, а нормальный случай, поэтому реакция тихая: длина множества не меняется.

Что вернёт add и почему нельзя писать s = s.add(x)?

add возвращает None: метод меняет множество на месте. Присваивание s = s.add(x) затирает множество значением None, и следующая работа с s падает с AttributeError. Вызывайте метод отдельной строкой без присваивания.

Как добавить в множество сразу несколько элементов?

Одним вызовом update: tags.update(['sql', 'web']) вольёт весь список. Можно перечислить несколько наборов через запятую — update([1, 2], {3}, 'ab') примет все. Число перебрать нельзя, поэтому одиночные значения и числа кладут add-ом.

Понравился урок? Сошлитесь на него

«add кладёт аргумент как есть, update разбирает аргумент на элементы.»

Скопируйте готовую ссылку в формате HTML, Markdown или чистый адрес и вставьте в статью на Habr, VC, Telegram-канал или свой блог — так о проекте узнают новые читатели.

TelegramVK

Что дальше

Осталось в разделе: 20 из 20. Прогресс хранится в вашем браузере.

Похожие уроки по темам

Подобраны автоматически по пересечению тем и ключевых слов.