Простой Python — страница 9 из 66

Кортежи, как и списки, являются последовательностями произвольных элементов. В отличие от списков кортежи неизменяемы. Это означает, что вы не можете добавить, удалить или изменить элементы кортежа после того, как определите его. Поэтому кортеж аналогичен константному списку.

Создание кортежей с помощью оператора ()

Синтаксис создания кортежей несколько необычен, как мы увидим в следующих примерах.

Начнем с создания пустого кортежа с помощью оператора ():

>>> empty_tuple = ()

>>> empty_tuple

()

Чтобы создать кортеж, содержащий один элемент или более, ставьте после каждого элемента запятую. Это вариант для кортежей с одним элементом:

>>> one_marx = 'Groucho',

>>> one_marx

('Groucho',)

Если в вашем кортеже более одного элемента, ставьте запятую после каждого из них, кроме последнего:

>>> marx_tuple = 'Groucho', 'Chico', 'Harpo'

>>> marx_tuple

('Groucho', 'Chico', 'Harpo')

При отображении кортежа Python выводит на экран скобки. Вам они совсем не нужны — кортеж определяется запятыми, — однако не повредят. Вы можете окружить ими значения, что позволяет сделать кортежи более заметными:

>>> marx_tuple = ('Groucho', 'Chico', 'Harpo')

>>> marx_tuple

('Groucho', 'Chico', 'Harpo')

Кортежи позволяют вам присвоить несколько переменных за один раз:

>>> marx_tuple = ('Groucho', 'Chico', 'Harpo')

>>> a, b, c = marx_tuple

>>> a

'Groucho'

>>> b

'Chico'

>>> c

'Harpo'

Иногда это называется распаковкой кортежа.

Вы можете использовать кортежи, чтобы обменять значения с помощью одного выражения, без применения временной переменной:

>>> password = 'swordfish'

>>> icecream = 'tuttifrutti'

>>> password, icecream = icecream, password

>>> password

'tuttifrutti'

>>> icecream

'swordfish'

>>>

Функция преобразования tuple() создает кортежи из других объектов:

>>> marx_list = ['Groucho', 'Chico', 'Harpo']

>>> tuple(marx_list)

('Groucho', 'Chico', 'Harpo')

Кортежи против списков

Вы можете использовать кортежи вместо списков, но они имеют меньше возможностей — у них нет функций append(), insert() и т. д., поскольку кортеж не может быть изменен после создания. Почему же не применять везде списки вместо кортежей?

• Кортежи занимают меньше места.

• Вы не сможете уничтожить элементы кортежа по ошибке.

• Вы можете использовать кортежи как ключи словаря (см. следующий раздел).

• Именованные кортежи (см. пункт «Именованные кортежи» раздела «Когда лучше использовать классы и объекты, а когда — модули» главы 6) могут служить более простой альтернативой объектам.

• Аргументы функции передаются как кортежи (см. раздел «Функции» главы 4).

Более детально рассматривать кортежи я не буду. При решении повседневных задач вы будете чаще использовать списки и словари. И это хороший повод перейти к следующей теме.

Словари

Словарь очень похож на список, но порядок элементов в нем не имеет значения, и они выбираются не с помощью смещения. Вместо этого для каждого значения вы указываете связанный с ним уникальный ключ. Таким ключом в основном служит строка, но он может быть объектом одного из неизменяемых типов: булевой переменной, целым числом, числом с плавающей точкой, кортежем, строкой и другими объектами, которые вы увидите далее. Словари можно изменять, что означает, что вы можете добавить, удалить и изменить их элементы, которые имеют вид «ключ — значение».

Если вы работали с другими языками программирования, которые поддерживают только массивы и списки, то полюбите словари.


В других языках программирования словари могут называться ассоциативными массивами, хешами или хеш-таблицей. В Python словарь также называется dict для экономии места.

Создание словаря с помощью {}

Чтобы создать словарь, вам нужно обернуть в фигурные скобки ({}) разделенные запятыми пары ключ: значение. Самым простым словарем является пустой словарь, не содержащий ни ключей, ни значений:

>>> empty_dict = {}

>>> empty_dict

{}

Создадим небольшой словарь, включающий цитаты из «Словаря сатаны» Амброза Бирса:

>>> bierce = {

…·····"day": "A period of twenty-four hours, mostly misspent",

…·····"positive": "Mistaken at the top of one's voice",

…·····"misfortune": "The kind of fortune that never misses",

…·····}

>>>

Ввод имени словаря в интерактивный интерпретатор выведет все его ключи и значения:

>>> bierce

{'misfortune': 'The kind of fortune that never misses',

'positive': "Mistaken at the top of one's voice",

'day': 'A period of twenty-four hours, mostly misspent'}


В Python допускается наличие запятой после последнего элемента списка, кортежа или словаря. Вам также не обязательно использовать выделение пробелами, как я это сделал в предыдущем примере, когда вы вводите ключи и значения внутри фигурных скобок. Это лишь улучшает читабельность.

Преобразование с помощью функции dict()

Вы можете использовать функцию dict(), чтобы преобразовывать последовательности из двух значений в словари. (Вы иногда можете столкнуться с последовательностями «ключ — значение» вида «Стронций, 90, углерод, 14» или «Vikings, 20, Packers, 7».) Первый элемент каждой последовательности применяется как ключ, а второй — как значение.

Для начала рассмотрим небольшой пример, использующий lol (список, содержащий списки, которые состоят из двух элементов):

>>> lol = [['a', 'b'], ['c', 'd'], ['e', 'f']]

>>> dict(lol)

{'c': 'd', 'a': 'b', 'e': 'f'}


Помните, что порядок ключей в словаре может быть произвольным, он зависит от того, как вы добавляете элементы.


Мы могли бы использовать любую последовательность, содержащую последовательности, которые состоят из двух элементов. Рассмотрим остальные примеры.

Список, содержащий двухэлементные кортежи:

>>> lot = [('a', 'b'), ('c', 'd'), ('e', 'f')]

>>> dict(lot)

{'c': 'd', 'a': 'b', 'e': 'f'}

Кортеж, включающий двухэлементные списки:

>>> tol = (['a', 'b'], ['c', 'd'], ['e', 'f'])

>>> dict(tol)

{'c': 'd', 'a': 'b', 'e': 'f'}

Список, содержащий двухсимвольные строки:

>>> los = ['ab', 'cd', 'ef']

>>> dict(los)

{'c': 'd', 'a': 'b', 'e': 'f'}

Кортеж, содержащий двухсимвольные строки:

>>> tos = ('ab', 'cd', 'ef')

>>> dict(tos)

{'c': 'd', 'a': 'b', 'e': 'f'}

В подразделе «Итерирование по нескольким последовательностям с помощью функции zip()» раздела «Выполняем итерации с помощью for» главы 4 вы познакомитесь с функцией, которая называется zip(). Она позволит вам легко создавать такие двухэлементные последовательности.

Добавление или изменение элемента с помощью конструкции [ключ]

Добавить элемент в словарь довольно легко. Нужно просто обратиться к элементу по его ключу и присвоить ему значение. Если ключ уже существует в словаре, имеющееся значение будет заменено новым. Если ключ новый, он и указанное значение будут добавлены в словарь. Здесь, в отличие от списков, вам не нужно волноваться о том, что Python сгенерирует исключение во время присваивания нового элемента, если вы укажете, что этот индекс находится вне существующего диапазона.

Создадим словарь, содержащий большинство членов Monty Python, используя их фамилии в качестве ключей, а имена — в качестве значений:

>>> pythons = {

…·····'Chapman': 'Graham',

…·····'Cleese': 'John',

…·····'Idle': 'Eric',

…·····'Jones': 'Terry',

…·····'Palin': 'Michael',

…·····}

>>> pythons

{'Cleese': 'John', 'Jones': 'Terry', 'Palin': 'Michael',

'Chapman': 'Graham', 'Idle': 'Eric'}

Здесь не хватает одного участника — уроженца Америки Терри Гиллиама. Перед вами попытка анонимного программиста добавить его, однако он ошибся, когда вводил имя:

>>> pythons['Gilliam'] = 'Gerry'

>>> pythons

{'Cleese': 'John', 'Gilliam': 'Gerry', 'Palin': 'Michael',

'Chapman': 'Graham', 'Idle': 'Eric', 'Jones': 'Terry'}

А вот код другого программиста, который исправил эту ошибку:

>>> pythons['Gilliam'] = 'Terry'

>>> pythons

{'Cleese': 'John', 'Gilliam': 'Terry', 'Palin': 'Michael',

'Chapman': 'Graham', 'Idle': 'Eric', 'Jones': 'Terry'}

Используя один и тот же ключ ('Gilliam'), мы заменили исходное значение 'Gerry' на 'Terry'.

Помните, что ключи в словаре должны быть уникальными. Именно поэтому мы в качестве ключей использовали фамилии, а не имена — двух участников Monty Python зовут Терри. Если вы применяете ключ более одного раза, победит последнее значение:

>>> some_pythons = {

…·····'Graham': 'Chapman',

…·····'John': 'Cleese',

…·····'Eric': 'Idle',

…·····'Terry': 'Gilliam',

…·····'Michael': 'Palin',

…·····'Terry': 'Jones',

…·····}

>>> some_pythons

{'Terry': 'Jones', 'Eric': 'Idle', 'Graham': 'Chapman',

'John': 'Cleese', 'Michael': 'Palin'}

Сначала мы присвоили значение 'Gilliam' ключу 'Terry', а затем заменили его на 'Jones'.

Объединение словарей с помощью функции update()

Вы можете использовать функцию update(), чтобы скопировать ключи и значения из одного словаря в другой.

Определим словарь pythons, содержащий имена всех участников:

>>> pythons = {

…·····'Chapman': 'Graham',

…·····'Cleese': 'John',

…·····'Gilliam': 'Terry',

…·····'Idle': 'Eric',

…·····'Jones': 'Terry',

…·····'Palin': 'Michael',

·····}

>>> pythons

{'Cleese': 'John', 'Gilliam': 'Terry', 'Palin': 'Michael',

'Chapman': 'Graham', 'Idle': 'Eric', 'Jones': 'Terry'}

Кроме того, у нас есть другой словарь, содержащий имена других юмористов и называющийся others:

>>> others = { 'Marx': 'Groucho', 'Howard': 'Moe' }

Теперь появляется еще один анонимный программист, который считает, что члены словаря others должны быть членами Monty Python:

>>> pythons.update(others)

>>> pythons

{'Cleese': 'John', 'Howard': 'Moe', 'Gilliam': 'Terry',

'Palin': 'Michael', 'Marx': 'Groucho', 'Chapman': 'Graham',

'Idle': 'Eric', 'Jones': 'Terry'}

Что произойдет, если во втором словаре будут находиться такие же ключи, что и в первом? Победит значение из второго словаря:

>>> first = {'a': 1, 'b': 2}

>>> second = {'b': 'platypus'}

>>> first.update(second)

>>> first

{'b': 'platypus', 'a': 1}

Удаление элементов по их ключу с помощью del

Код нашего анонимного программиста был корректным — технически. Но он не должен был его писать! Члены словаря others, несмотря на свою известность и чувство юмора, не участвовали в Monty Python. Отменим добавление последних двух элементов:

>>> del pythons['Marx']

>>> pythons

{'Cleese': 'John', 'Howard': 'Moe', 'Gilliam': 'Terry',

'Palin': 'Michael', 'Chapman': 'Graham', 'Idle': 'Eric',

'Jones': 'Terry'}

>>> del pythons['Howard']

>>> pythons

{'Cleese': 'John', 'Gilliam': 'Terry', 'Palin': 'Michael',

'Chapman': 'Graham', 'Idle': 'Eric', 'Jones': 'Terry'}

Удаление всех элементов с помощью функции clear()

Чтобы удалить все ключи и значения из словаря, вам следует использовать функцию clear() или просто присвоить пустой словарь заданному имени:

>>> pythons.clear()

>>> pythons

{}

>>> pythons = {}

>>> pythons

{}

Проверяем на наличие ключа с помощью in

Если вы хотите узнать, содержится ли в словаре какой-то ключ, используйте ключевое слово in. Снова определим словарь pythons, но на этот раз опустим одного-двух участников:

>>> pythons = {'Chapman': 'Graham', 'Cleese': 'John',

'Jones': 'Terry', 'Palin': 'Michael'}

Теперь проверим, кого мы добавили:

>>> 'Chapman' in pythons

True

>>> 'Palin' in pythons

True

Вспомнили ли мы о Терри Гиллиаме на этот раз?

>>> 'Gilliam' in pythons

False

Черт.

Получение элемента словаря с помощью конструкции [ключ]

Этот вариант использования словаря — самый распространенный. Вы указываете словарь и ключ, чтобы получить соответствующее значение:

>>> pythons['Cleese']

'John'

Если ключа в словаре нет, будет сгенерировано исключение:

>>> pythons['Marx']

Traceback (most recent call last):

··File "", line 1, in 

KeyError: 'Marx'

Есть два хороших способа избежать возникновения этого исключения. Первый из них — проверить, имеется ли заданный ключ, с помощью ключевого слова in, что вы уже видели в предыдущем разделе:

>>> 'Marx' in pythons

False

Второй способ — использовать специальную функцию словаря get(). Вы указываете словарь, ключ и опциональное значение. Если ключ существует, вы получите связанное с ним значение:

>>> pythons.get('Cleese')

'John'

Если такого ключа нет, получите опциональное значение, если указывали его:

>>> pythons.get('Marx', 'Not a Python')

'Not a Python'

В противном случае будет возвращен объект None (интерактивный интерпретатор не выведет ничего):

>>> pythons.get('Marx')

>>>

Получение всех ключей с помощью функции keys()

Вы можете использовать функцию keys(), чтобы получить все ключи словаря. Для следующих примеров мы берем другой словарь:

>>> signals = {'green': 'go', 'yellow': 'go faster', 'red': 'smile for the camera'}

>>> signals.keys()

dict_keys(['green', 'red', 'yellow'])


В Python 2 функция keys() возвращает простой список. В Python 3 эта функция возвращает dict_keys() — итерабельное представление ключей. Это удобно для крупных словарей, поскольку не требует времени и памяти для создания и сохранения списка, которым вы, возможно, даже не воспользуетесь. Но зачастую вам нужен именно список. В Python 3 надо вызвать функцию list(), чтобы преобразовать dict_keys в список:

>>> list(signals.keys())

['green', 'red', 'yellow']


В Python 3 вам также понадобится использовать функцию list(), чтобы преобразовать результат работы функций values() и items() в обычные списки. Я пользуюсь этой функцией в своих примерах.

Получение всех значений с помощью функции values()

Чтобы получить все значения словаря, используйте функцию values():

>>> list(signals.values())

['go', 'smile for the camera', 'go faster']

Получение всех пар «ключ — значение» с помощью функции items()

Когда вам нужно получить все пары «ключ — значение» из словаря, используйте функцию items():

>>> list(signals.items())

[('green', 'go'), ('red', 'smile for the camera'), ('yellow', 'go faster')]

Каждая пара будет возвращена как кортеж вроде ('green', 'go').

Присваиваем значения с помощью оператора =, копируем их с помощью функции copy()

Как и в случае со списками, если вам нужно внести в словарь изменение, оно отразится для всех имен, которые ссылаются на него.

>>> signals = {'green': 'go', 'yellow': 'go faster', 'red': 'smile for the camera'}

>>> save_signals = signals

>>> signals['blue'] = 'confuse everyone'

>>> save_signals

{'blue': 'confuse everyone', 'green': 'go',

'red': 'smile for the camera', 'yellow': 'go faster'}

Чтобы скопировать ключи и значения из одного словаря в другой и избежать этого, вы можете воспользоваться функцией copy():

>>> signals = {'green': 'go', 'yellow': 'go faster', 'red': 'smile for the camera'}

>>> original_signals = signals.copy()

>>> signals['blue'] = 'confuse everyone'

>>> signals

{'blue': 'confuse everyone', 'green': 'go',

'red': 'smile for the camera', 'yellow': 'go faster'}

>>> original_signals

{'green': 'go', 'red': 'smile for the camera', 'yellow': 'go faster'}

Множества