Кортежи и множества
Список — универсальная коллекция. Но есть ещё два типа, которые делают некоторые задачи проще и быстрее: кортежи и множества.
Кортежи
Кортеж (tuple) похож на список, но его нельзя изменить. Записывается в круглых скобках:
point = (3, 5)
print(point[0]) # 3
point[0] = 10 # ошибка: кортеж неизменяем
Кортежи удобны, чтобы хранить несколько связанных значений вместе: координаты, «имя и возраст», «день и температура».
Распаковка
Кортеж можно разложить по переменным — мы уже делали это при вводе:
x, y = (3, 5)
name, age = "Лена", 14 # скобки можно не писать
Отсюда удобный приём — обмен значений без третьей переменной:
a, b = 1, 2
a, b = b, a # теперь a = 2, b = 1
Список кортежей
cities = [("Казань", 1300), ("Тверь", 400), ("Пермь", 1000)]
for name, population in cities:
print(name, population)
Сравнение и сортировка кортежей
Кортежи сравниваются поэлементно: сначала первые элементы, при равенстве — вторые и так далее.
print((1, 9) < (2, 0)) # True — решает первый элемент
print((2, "б") < (2, "в")) # True — первые равны, решает второй
Поэтому список кортежей сортируется сразу по нескольким признакам:
fruits = [(3, "груша"), (1, "яблоко"), (3, "банан")]
fruits.sort()
print(fruits) # [(1, 'яблоко'), (3, 'банан'), (3, 'груша')]
Сначала по числу, а при равных числах — по названию. Чтобы по одному признаку сортировать по убыванию, а по другому по возрастанию, можно хранить число с минусом: (-число, название). Так меньшее «минус число» соответствует большему числу.
Множества
Множество (set) хранит значения без повторов и без порядка:
colors = {"красный", "синий", "красный"}
print(len(colors)) # 2
empty = set() # пустое множество (не {} — это словарь)
Добавление и проверка:
seen = set()
seen.add(5)
seen.add(5) # повтор не добавится
print(5 in seen) # True
seen.discard(5) # удалить, если есть
Почему множества быстрые
Проверка x in список перебирает элементы по одному: для списка из 105 элементов это 105 сравнений. Проверка x in множество занимает одну операцию независимо от размера. Если в цикле много раз спрашиваешь «было ли уже такое значение?», храни увиденное во множестве.
nums = [4, 7, 4, 1, 7, 7]
seen = set()
first_repeat = None
for x in nums:
if x in seen:
first_repeat = x
break
seen.add(x)
print(first_repeat) # 4
Операции над множествами
a = {1, 2, 3, 4}
b = {3, 4, 5}
print(a | b) # {1, 2, 3, 4, 5} — объединение
print(a & b) # {3, 4} — пересечение
print(a - b) # {1, 2} — разность
print(a ^ b) # {1, 2, 5} — есть ровно в одном
Множество из списка: set(список). Так быстро убирают повторы: len(set(a)) — сколько разных значений в списке.
Порядок не гарантирован
У множества нет порядка элементов: печать print(s) может выдать их в неожиданной последовательности. Если в задаче нужен порядок, сделай sorted(s).
В множестве могут лежать только неизменяемые значения: числа, строки, кортежи. Список положить во множество нельзя.
Итог
- кортеж
(a, b)— неизменяемый набор значений; распаковкаx, y = t, обменa, b = b, a; - кортежи сравниваются поэлементно — сортировка списка кортежей учитывает несколько признаков;
- множество хранит значения без повторов,
x in sработает за одну операцию; | & - ^— объединение, пересечение, разность, симметрическая разность;- у множества нет порядка — для вывода сортируй.