Чем множество отличается от списка в питоне
Перейти к содержимому

Чем множество отличается от списка в питоне

  • автор:

Python для начинающих: какая разница между tuple, list и set?

Язык программирования Python предоставляет четыре встроенных типа данных для хранения коллекций из объектов. Все они наделены различными свойствами и характеристиками: list (список), tuple (кортеж), set (множество) и dictionary (словарь).

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

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

Зачем вообще выбирать?

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

Может стог сена — это список? Как насчет кортежа? Почему бы не использовать множества всегда? На какие предостережения следует обратить внимание?

Отличия между списком, кортежем и множеством

  • Отличие 1: дубликаты.
    Говоря проще, List и Tuple в Python как двойняшки разного пола, а тип данных Set для них как двоюродный брат. В отличие от списков или кортежей, множество не содержит дубликатов. Другими словами, элементы множества всегда уникальны. Получается, что множество удобно удаляет дубликаты, словно создано именно для этого.
set_example = 
# fruit_set =
#
  • Отличие 2: упорядоченность.
    Наверняка вы слышали утверждение “множества и словари в Python не упорядочены”, но на сегодняшний день — это лишь половина правды в зависимости от того, какой версией Python вы пользуетесь. До Python версии 3.6 словари и множества действительно не сохраняли порядок элементов, но начиная с Python 3.7, dictionary и set официально упорядочены по времени добавления элементов. А вот list и tuple — это всегда упорядоченные последовательности объектов.
# Пример тогда ещё неупорядоченного множества в Python версии 3.5fruit_size = <> 
>>> fruit_size['��'] = 12
>>> fruit_size['��'] = 16
>>> fruit_size['��'] = 20
>>> fruit_size
  • Отличие 3: индексация.
    Что списки, что кортежи — оба поддерживают индексацию и срезы, а вот множества — нет.
fruit_list = ['��', '��', '��']
fruit_list[1]
# '��'
animal_tuple = ('��', '��', '��')
animal_tuple[2]
# '��'
vehicle_set =
vehicle_set[0]
# TypeError: 'set' object is not subscriptable

Когда выбирать список, а когда — кортеж?

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

a_tuple = tuple(range(1000))
a_list = list(range(1000))
a_tuple.__sizeof__() # 8024 байта
a_list.__sizeof__() # 9088 байт
  • Список подходит, если:
  1. Последовательность планируется изменять.
  2. Планируется постепенно добавлять новые элементы в последовательность или удалять старые.
  • Кортеж подходит, если:
  1. Последовательность НЕ планируется изменять.
  2. Все, что нужно от последовательности — это возможность поочередно перебирать постоянный набор элементов.
  3. Нужна последовательность элементов для ее назначения в качестве ключа словаря. Поскольку списки — это изменяемый тип данных, их нельзя применять в качестве ключей словаря.
  4. Важна скорость выполнения операций с последовательностью: из-за отсутствия возможности изменения, кортежи работают куда быстрее списков.

Когда выбирать множества?

Базовая структура типа данных “множество” — это хеш-таблица (Hash Table). Поэтому множества очень быстро справляются с проверкой элементов на вхождение, например содержится ли объект x в последовательности a_set .

Идея заключается в том, что поиск элемента в хэш-таблице — это операция O(1), то есть операция с постоянным временем выполнения.

Получается, всегда надо использовать множество?

По сути, если не нужно хранить дубликаты, то множество будет лучшим выбором, чем список.

Выводы

“Преждевременная оптимизация — корень всех зол”.

Итак, самое главное, что вам стоит запомнить по поводу списков, кортежей и множеств.

  1. Если необходимо хранить дубликаты, то выбирайте список или кортеж.
  2. Если НЕ планируется изменять последовательность после ее создания, то выбирайте кортеж, а не список.
  3. Если НЕ нужно хранить дубликаты, то воспользуйтесь множеством, так как они значительно быстрее определяют наличие объекта в последовательности.

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

Главное — помнить о похожих чертах и особенностях встроенных типов данных Python.

  • Скрейпинг PDF с нуля на Python: библиотеки tabula-py и Pandas
  • Как вычислить миллионное число Фибоначчи на Python
  • 3 важных рекомендации Django-программистам

Чем отличаются list, tuple и set? Зачем они нужны?

List (список), tuple (кортеж), set (множество) — это встроенные структуры данных языка python. Каждая из них имеет свои возможности и ограничения. Это позволяет выбрать наиболее подходящий способ хранения информации в программе.

List (список)

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

Создание списка
>>> my_list = [] # Создание пустого списка с помощью литерала списка >>> my_list = list() # Создание пустого списка с помощью встроенной функции >>> >>> my_list = [1,2,['a','b'],4,5] # Инициализация списка >>> >>> my_list = list('hello world') # Создание списка из итерируемого объекта >>> my_list ['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd'] >>> >>> my_list = [x for x in range(10)] # Генератор списков в действии >>> my_list [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
Доступные методы
  • my_list.append(x) — добавляет x в конец списка
  • my_list.clear() — очищает список
  • my_list.copy() — возвращает копию списка my_list
  • my_list.count(x) — возвращает кол-во элементов со значением x
  • my_list.extend(x) — добавляет элементы списка x к концу списка my_list
  • my_list.index(x,start,end) — возвращает индекс первого найденного x, можно задать промежуток для поиска (опционально)
  • my_list.insert(index, x) — вставляет x на заданную позицию
  • my_list.pop(index) — возвращает элемент с указанным индексом и удаляет его, если индекс не указан — возвращается и удаляется последний элемент
  • my_list.remove(x) — удаляет первый элемент со значением x
  • my_list.reverse() — инвертирует порядок элементов в списке
  • my_list.sort(key=x) сортирует список на основе функции x
В каких случаях использовать?

Для хранения элементов, объединенных каким либо признаком. В случае, если изменение элементов и/или расширение списка не предполагается, следует использовать неизменяемый аналог — кортеж.

Tuple (кортёж)

Кортеж — это неизменяемый и более быстрый аналог списка. Он защищает хранимые данные от непреднамеренных изменений и может использоваться в качестве ключа в словарях (словарь — ассоциативный массив в python).

Создание кортежа.
>>> my_tuple = () # Создание кортежа с помощью литерала >>> my_tuple = tuple() # Создание кортежа с помощью встроенной функции >>> >>> my_tuple = (1,2,['a','b'],4,5) # Инициализация кортежа >>> >>> my_tuple = tuple('hello world') # Создание кортежа из итерируемого объекта >>> my_tuple ('h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd') >>> >>> my_tuple = tuple(2**x for x in [0, 1, 2, 3]) # Генератор кортежей >>> my_tuple (1, 2, 4, 8) 
Доступные методы
  • my_tuple.count(x) — возвращает кол-во элементов со значением x
  • my_tuple.index(x,start,end) — возвращает индекс первого найденного x, можно задать промежуток для поиска (опционально)
В каких случаях использовать?

Для хранения данных вместо списка (если они не предполагают изменений).

Set (множество)

Множество — это набор уникальных элементов в случайном порядке (неупорядоченный список). Множества примечательны тем, что операция проверки “принадлежит ли объект множеству” происходит значительно быстрее аналогичных операций в других структурах данных.

Создание множества
>>> my_something = > # . Попытка создать множество при помощи литерала даст нам словарь >>> type(my_something) class 'dict'> >>> >>> my_set = set() # Создание при помощи встроенной функции >>> >>> my_set = 1,2,3,4,5> # Инициализация множества >>> >>> my_set = set('hello world') # Создания множества из итерируемого объекта >>> my_set 'r', 'o', 'e', 'h', 'd', 'w', 'l', ' '> >>> >>> my_set = x for x in range(10)> # Генератор множеств >>> my_set 0, 1, 2, 3, 4, 5, 6, 7, 8, 9> 
Доступные методы
  • my_set.add(x) — добавляет x во множество
  • my_set.difference(x) — возвращает множество элементов my_set, которые не входят во множество x
  • my_set.difference_update(x) — удаляет из множества my_set все элементы, которые входят во множество x
  • my_set.discard(x) — удаляет элемент x из my_set
  • my_set.intersection(x) — возвращает элементы общие для множеств my_set и x
  • my_set.intersection_update(x) — удаляет из множества my_set элементы, которых нет во множестве x
  • my_set.isdisjoint(x) — возвращает true если my_set и x не содержат одинаковых значений
  • my_set.issubset(x) — возвращает true если все элементы my_set входят во множество x
  • my_set.issuperset(x) — возвращает true если все элементы x входят во множество my_set
  • my_set.pop() — возвращает и удаляет первый (на данный момент) элемент множества
  • my_set.remove(x) — удаляет x из множества
  • my_set.symmetric_difference(x) — возвращает все элементы из x и my_set, которые встречаются только в одном из множеств
  • my_set.symmetric_difference_update(x) — обновляет исходное множество таким образом, что оно будет состоять из всех элементов x и my_set, которые встречаются только в одном из множеств
  • my_set.union(x) — возвращает новое множество, состоящее из всех элементов x и my_set
  • my_set.update(x) — добавляет в my_set все элементы x
В каких случаях использовать?

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

Попробуйте бесплатные уроки по Python

Получите крутое код-ревью от практикующих программистов с разбором ошибок и рекомендациями, на что обратить внимание — бесплатно.

Переходите на страницу учебных модулей «Девмана» и выбирайте тему.

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

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

Массивы данных в Python реализованы достаточно своеобразно, что сильно отличает его от других языков программирования. Если вы изучаете Python как второй язык, то его структуры мягко говоря, вызывают недоумение. Если же вы начнёте изучать другой язык после Python’а, то сильно удивитесь отсутствию списков, кортежей, словарей и множеств.

В других языках, да и вообще в программировании, такие структуры называются одним словом: массивы. Но в Python это приводит к путанице, поскольку используя синтаксис массивов, применяются другие названия, а под словом «массив» подразумевается вообще отдельная библиотека. Попробуем разобраться во всех этих хитростях.

Общее понятие массива данных в программировании

Предположим у нас есть несколько клиентов, которые различаются по имени. Без массива пришлось бы сделать примерно так (код на PHP):

$client1 = 'Маша'; $client2 = 'Вася'; $client3 = 'Аня';

Под массивом обычно принимается набор элементов. В большинстве языков для массивов используются квадратные скобки.

$clients = ['Маша', 'Вася', 'Аня'];

Массив предполагает использование индекса смещения. Например, так можно получить первый элемент, у которого нулевое смещение:

print($clients[0]);

Точно также можно изменить элемент, обратившись к нему по индексу.

$clients[1] = 'Петя';

То есть элементы массива представляют собой упорядоченное расположение элементов в памяти.

Есть ещё одна разновидность массивов, которая называется ассоциативным массивом. Он использует пару «ключ-значение».

$client = [ 'name' => 'Маша', 'city' => 'Киев', 'year' => '1998' ];

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

print($client['city']);

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

Отличия Python: список и словарь

Python не использует слово «массив» и это часто вносит путаницу. Вместо этого Python разделяет понятие массива на список (list) и словарь (dict).

Список задаётся точно также, как и обычный массив и с ним можно делать все те же операции:

Clients = ['Маша', 'Вася', 'Аня'] print(Clients[0]) Clients[1] = 'Петя' print(Clients) # ['Маша', 'Петя', 'Аня']

Но список не может быть ассоциативным массивом. Ассоциативный массив в Python — это словарь:

Client = < 'name': 'Маша', 'city': 'Киев', 'year': '1998' >print(Client['city']) # Киев

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

Таким образом первое отличие Python — вместо слова «массив» следует использовать «список» или «словарь», чтобы показать его устройство.

Неизменяемый список — кортеж

Python выделяет особый вид списка, который будет неизменяемым — кортеж (tuple). Если в списке можно изменить любой элемент, то кортеж задаётся только один раз и больше не меняется.

t = ('Маша', 'Вася', 'Аня') t[1] = 'Петя' # TypeError: 'tuple' object does not support item assignment

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

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

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

t = 'Маша', 'Вася', 'Аня' print(t[1]) # 'Вася'

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

t = 'Маша', print(t[0]) # 'Маша'

Если запятую убрать, то мы получим, что переменная содержит обычную строку. Из-за этой особенности, желательно для всех кортежей добавлять запятую в конце перечисления значений.

t = 'Маша', 'Вася', 'Аня',

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

Множество set

Ещё одной отличительной чертой Python является набор уникальных элементов множество (set). По своей сути — это тот же словарь, только состоящий из ключей.

st = print(st) #

Множество используется там, где нужно получить уникальные значения. Часто можно встретить задачу, где нужно убрать дубли из списка. Для этого список преобразуется в множество, потом обратно в список:

inElement = [‘planet’, ‘sputnik’, ‘planet’] inElement = list(set(inElement)) print(inElement) #

В других языках для этого используются просто функции, но в Python почему-то требуется преобразование типа «туда-сюда», при котором может измениться последовательность элементов.

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

d1 = d1.add(‘comet’) print(d1) # d1.remove(‘planet’) print(d1) #

Есть разновидность множества — frozenset. В отличие от обычного, его нельзя изменить. Задаётся с помощью одноимённой функции:

fset = frozenset() fset.add(4) # AttributeError: 'frozenset' object has no attribute 'add'

Возникает вопрос зачем вообще нужны множества, если с ними столько нюансов? Дело в том, что Python предлагает много операций над множествами. Это очень похоже на SQL-команды UNION или даже JOIN, где происходит объединение результатов по разным алгоритмам.

# комбинации множеств a = b = # пересечение — элементы в обоих множествах print(a & b) # print(a.intersection(b)) # — или так # объединение print(a | b) # print(a.union(b)) # — или так # разность (те, что в первом, но нет во втором множестве) print(a - b) # print(a.difference(b)) # — или так # исключающие ИЛИ print(a ^ b) # print(a.symmetric_difference(b)) # — или так

Модуль array

Чтобы мы окончательно запутались, Python предлагает ещё и модуль array с помощью которого можно создавать те же списки, только определенного типа данных.

Зачем это нужно? Это некая имитация того, что есть в языках со строгой типизацией. Например в Паскале (Java и многие другие языки) следует указывать из какого типа данных будет состоять массив. Это сделано для того, чтобы можно было определить сколько памяти нужно выделить под переменную.

var a: array[1..10] of integer;

Поскольку в Python динамическая типизация, то сделать подобное можно так:

import array ar = array.array('i', [1, 2, 3, 4, 5])

Дальше работа с происходит с помощью методов модуля array.

Итого

Массивы часто используются в программах. Нужно просто запомнить, что в Python они делятся на разные варианты. В 99% случаев хватает списков и словарей.

Кортежи используются для тех случаев, когда хотят особо обратить внимание, что элементы не требуют изменения. Какого-то принципиального выигрыша (в скорости и памяти) по сравнению со списком не будет, так что это больше относится к стилю программированию.

Множества — самый «капризный» вариант — их следует использовать только там где требуется уникальность элементов. В Python нет нормальной встроенной функции для удаления дублей из списков, поэтому приходится использовать set() . Поэтому кажется, что списки постоянно используются, но нет, это скорее вынужденная мера, чтобы не изобретать свой велосипед или использовать дополнительные модули, вроде itertools.

На собеседованиях часто пытаются проверить знания этих особенностей Python. Например подсовывают код, где пытаться изменить кортеж или получить элемент множества по индексу. Это 100% уловка на внимательность. К реальному программированию это имеет мало отношения — просто достаточно знать особенности массивов Python, чтобы их полноценно использовать.

Списки, словари и множества в Python

У разработчиков типа данных list Python было много вариантов каким сделать его во время реализации. Каждый выбор повлиял на то, как быстро список мог выполнять операции. Одно из решений было сделать список оптимальным для частых операций.

Индексирование и присваивание

Две частые операции — индексирование и присваивание на позицию индекса. В списках Python значения присваиваются и извлекаются из определенных известных мест памяти. Независимо от того, насколько велик список, индексный поиск и присвоение занимают постоянное количество времени и, таким образом их трудоемкость O(1).

Pop, Shift, Delete

Извлечение элемента(pop) из списка Python по умолчанию выполняется с конца, но, передавая индекс, вы можете получить элемент из определенной позиции. Когда pop вызывается с конца, операция имеет сложность O(1) , а вызов pop из любого места — O(n). Откуда такая разница?

Когда элемент берется из середины списка Python, все остальные элементы в списке сдвигаются на одну позицию ближе к началу. Это суровая плата за возможность брать индекс за O(1), что является более частой операцией.

По тем же причинам вставка в индекс — O(N); каждый последующий элемент должен быть сдвинут на одну позицию ближе к концу, чтобы разместить новый элемент. Неудивительно, что удаление ведет себя таким же образом.

Итерирование

Итерирование выполняется за O(N), потому что для итерации по N элементам требуется N шагов. Это также объясняет, почему оператор in, max, min в Python является O(N): чтобы определить, находится ли элемент в списке, мы должны перебирать каждый элемент.

Срезы

Чтобы получить доступ к фрагменту [a: b] списка, мы должны перебрать каждый элемент между индексами a и b. Таким образом, доступ к срезу — O(k), где k — размер среза. Удаление среза O(N) по той же причине, что удаление одного элемента — O(N): N последующих элементов должны быть смещены в сторону начала списка.

Умножение на int

Чтобы понять умножение списка на целое k, вспомним, что конкатенация выполняется за O(M), где M — длина добавленного списка. Из этого следует, что умножение списка равно O(N k), так как умножение k-размера списка N раз потребует времени k (N-1).

Разворот списка

Разворот списка — это O(N), так как мы должны переместить каждый элемент.

2. Множества

Множество (set)

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

Действия, которые можно выполнять с множеством:

  1. добавлять и удалять элементы,
  2. проверять принадлежность элемента множеству,
  3. перебирать его элементы,
  4. выполнять операции над множествами (объединение, пересечение, разность).

Операция “проверить принадлежность элемента” выполняется в множестве намного быстрее, чем в списке.

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

Изменяемые типы данных не могут быть элементами множества, в частности, нельзя сделать элементом множества список (вместо этого используйте неизменяемый кортеж) или другое множество. Требование неизменяемости элементов множества накладывается особенностями представления множества в памяти компьютера.

Задание множеств

Множество задается перечислением в фигурных скобках. Например:

Исключением явлеется пустое множество:

A = set() # A -- множество D = <> # D -- не пустое множество, а пустой словарь!

Если функции set передать в качестве параметра список, строку или кортеж, то она вернет множество, составленное из элементов списка, строки, кортежа. Например:

>>> A = set('qwerty') >>> print(A) .

Каждый элемент может входить в множество только один раз.

>>> A = >>> B = >>> print(A == B) # A и B — равные множества. True >>> set(‘Hello’)

Работа с элементами множеств

Операция Значение Трудоемкость
x in A принадлежит ли элемент x множеству A (возвращают значение типа bool ) O(1)
x not in A то же, что not x in A O(1)
A.add(x) добавить элемент x в множество A O(1)
A.discard(x) удалить элемент x из множества A O(1)
A.remove(x) удалить элемент x из множества A O(1)
A.pop() удаляет из множества один случайный элемент и возвращает его O(1)

Как мы видим, по времени стандартные оперцаии с одним элементом множества выполняются за O(1).

Поведение discard и remove различается тогда, когда удаляемый элемент отсутствует в множестве: discard не делает ничего, а метод remove генерирует исключение KeyError . Метод pop также генерирует исключение KeyError , если множество пусто.

При помощи цикла for можно перебрать все элементы множества:

Primes = for num im Primes: print(num)

Из множества можно сделать список при помощи функции list :

>>> A = >>> B = list(A) [1, 2, 3, 4, 5]
Упражнение №2

Вывести на экран все элементы множества A, которых нет в множестве B.

A = set('bqlpzlkwehrlulsdhfliuywemrlkjhsdlfjhlzxcovt') B = set('zmxcvnboaiyerjhbziuxdytvasenbriutsdvinjhgik') for x in A: .

Операции с множествами, обычные для математики

Операция Значение Трудоемкость
A | B
A.union(B)
Возвращает множество, являющееся объединением множеств A и B . O(len(A)+len(B))
A | = B
A.update(B)
Записывает в A объединение множеств A и B . O(len(A)+len(B))
A & B
A.intersection(B)
Возвращает множество, являющееся пересечением множеств A и B . O(min(len(A), len(B))
A &= B
A.intersection_update(B)
Записывает в A пересечение множеств A и B . O(min(len(A), len(B))
A — B
A.difference(B)
Возвращает разность множеств A и B (элементы, входящие в A, но не входящие в B). O(len(A)+len(B))
A -= B
A.difference_update(B)
Записывает в A разность множеств A и B . O(len(A)+len(B))
A ^ B
A.symmetric_difference(B)
Возвращает симметрическую разность множеств A и B (элементы, входящие в A или в B, но не в оба из них одновременно). O(len(A)+len(B))
A ^= B
A.symmetric_difference_update(B)
Записывает в A симметрическую разность множеств A и B . O(len(A)+len(B))
A A.issubset(B) Возвращает True, если A является подмножеством B. O(len(A))
A >=
B A.issuperset(B)
Возвращает True, если B является подмножеством A. O(len(B))
A < B Эквивалентно A

O(len(A))
A > B Эквивалентно A >= B and A != B O(len(B))

В случае, если нужно провести процедуру, затрагивающую все элементы множества, то его трудоемкость будет O(N).

3. Словари

Словарь (ассоциативный массив, dict)

В массиве или в списке индекс — это целое число. Традиционной является следующая ситуация:

>>> Days = ['Sunday', 'Monday', 'Tuesday', 'Wednessday', 'Thursday', 'Friday', 'Saturday'] >>> Days[0] 'Sunday' >>> Days[1] 'Monday'

А как реализовать обратное соответствие?

>>> Days['Sunday'] 0 >>> Days['Monday'] 1

При помощи списка или массива это сделать невозможно, нужно использовать ассоциативный массив или словарь.

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

Days = < 'Sunday': 0, 'Monday': 1, 'Tuesday': 2, 'Wednessday': 3, 'Thursday': 4, 'Friday': 5, 'Saturday': 6 >>>> Days['Sunday'] 0 >>> Days['Monday'] 1 >>> Days['Yesterday'] Traceback (most recent call last): File "", line 1, in KeyError: 'Yesterday'

При попытке обратиться к несуществующему элементу ассоциативного массива мы получаем исключение KeyError .

Особенностью ассоциативного массива является его динамичность: в него можно добавлять новые элементы с произвольными ключами и удалять уже существующие элементы.

>>> Days['Yesterday'] = -1 >>> print(Days['Yesterday']) -1

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

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

>>> Days['Tomorrow'] = -1 >>> Days['Yesterday'] == Days['Tomorrow'] True

Ключом может быть произвольный неизменяемый тип данных: целые и действительные числа, строки, кортежи. Ключом в словаре не может быть множество, но может быть элемент типа frozenset: специальный тип данных, являющийся аналогом типа set, который нельзя изменять после создания. Значением элемента словаря может быть любой тип данных, в том числе и изменяемый.

Создание словаря

Пустой словарь можно создать при помощи функции dict() или пустой пары фигурных скобок <> (вот почему фигурные скобки нельзя использовать для создания пустого множества).

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

Capitals = Capitals = dict(Russia = 'Moscow', Ukraine = 'Kiev', USA = 'Washington') Capitals = dict([("Russia", "Moscow"), ("Ukraine", "Kiev"), ("USA", "Washington")]) Capitals = dict(zip(["Russia", "Ukraine", "USA"], ["Moscow", "Kiev", "Washington"]))

Также можно использовать генерацию словаря через Dict comprehensions:

Cities = [«Moscow», «Kiev», «Washington»] States = [«Russia», «Ukraine», «USA»] CapitalsOfState =

Это особенно полезно, когда нужно «вывернуть» словарь наизнанку:

StateByCapital =

Операции с элементами словарей

Операция Значение Трудоемкость
value = A[key] Получение элемента по ключу. Если элемента с заданным ключом в словаре нет, то возникает исключение KeyError. O(1)
value = A.get(key) Получение элемента по ключу. Если элемента в словаре нет, то get возвращает None. O(1)
value = A.get(key, default_value) То же, но вместо None метод get возвращает default_value. O(1)
key in A Проверить принадлежность ключа словарю. O(1)
key not in A То же, что not key in A. O(1)
A[key] = value Добавление нового элемента в словарь. O(1)
del A[key] Удаление пары ключ-значение с ключом key. Возбуждает исключение KeyError, если такого ключа нет. O(1)
if key in A: del A[key] Удаление пары ключ-значение с предварительной проверкой наличия ключа. O(1)
try: del A[key] except KeyError: pass Удаление пары ключ-значение с перехватыванием и обработкой исключения. O(1)
value = A.pop(key) Удаление пары ключ-значение с ключом key и возврат значения удаляемого элемента.Если такого ключа нет, то возбуждается KeyError. O(1)
value = A.pop(key, default_value) То же, но вместо генерации исключения возвращается default_value. O(1)
A.pop(key, None) Это позволяет проще всего организовать безопасное удаление элемента из словаря. O(1)
len(A) Возвращает количество пар ключ-значение, хранящихся в словаре. O(1)

Перебор элементов словаря по ключу

for key in A: print(key, A[key])

Представления элементов словаря

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

  • Метод keys возвращает представление ключей всех элементов.
  • Метод values возвращает представление всех значений.
  • Метод items возвращает представление всех пар (кортежей) из ключей и значений.
>>> A = dict(a='a', b='b', c='c') >>> k = A.keys() >>> v = A.values() >>> k, v (dict_keys(['c', 'b', 'a']), dict_values(['c', 'b', 'a'])) >>> A['d'] = 'a' >>> k, v (dict_keys(['d', 'c', 'b', 'a']), dict_values(['a', 'c', 'b', 'a']))

Учтите что итерироваться по представлениям изменяя словарь нельзя

>>> for key in A.keys(): . del A[key] . Traceback (most recent call last): File "", line 1, in RuntimeError: dictionary changed size during iteration

Можно, если в начале скопировать представление в список

>>> for key in list(A.keys()): . del A[key] . >>> A <>

Пример использования словаря

# Создадим пустой словать Capitals Capitals = dict() # Заполним его несколькими значениями Capitals['Russia'] = 'Moscow' Capitals['Ukraine'] = 'Kiev' Capitals['USA'] = 'Washington' # Считаем название страны print('В какой стране вы живете?') country = input() # Проверим, есть ли такая страна в словаре Capitals if country in Capitals: # Если есть - выведем ее столицу print('Столица вашей страны', Capitals[country]) else: # Запросим название столицы и добавим его в словарь print('Как называется столица вашей страны?') city = input() Capitals[country] = city

Трудоемкость стандартных операций

Второй основной тип данных Python — это словарь. Как вы помните, словарь отличается от списка возможностью доступа к элементам по ключу, а не позиции. На данный момент наиболее важной характеристикой является то, что получение и присваивание элемента в словаре являются операциями за O(1).

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

Другая важная операция словаря — проверка наличия ключа в словаре. Операция contains также работает за O(1) (в случае со списками это занимало O(N)), потому что проверка для данного ключа подразумевает простое получение элемента по ключу, которое делается за O(1).

Когда нужно использовать словари

Словари нужно использовать в следующих случаях:

  • Подсчет числа каких-то объектов. В этом случае нужно завести словарь, в котором ключами являются объекты, а значениями — их количество.
  • Хранение каких-либо данных, связанных с объектом. Ключи — объекты, значения — связанные с ними данные. Например, если нужно по названию месяца определить его порядковый номер, то это можно сделать при помощи словаря Num[‘January’] = 1; Num[‘February’] = 2; .
  • Установка соответствия между объектами (например, “родитель—потомок”). Ключ — объект, значение — соответствующий ему объект.
  • Если нужен обычный массив, но при этом масимальное значение индекса элемента очень велико, но при этом будут использоваться не все возможные индексы (так называемый “разреженный массив”), то можно использовать ассоциативный массив для экономии памяти.

4. Задача №3768. Контрольная по ударениям

Вариант 1. Используем множество

Вариант 2. Используем словарь

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *