Коллекции — Ключевые аспекты разработки на Python
Вероятно, тема текущего урока — самая простая и самая базовая из всего, что описывалось и будет описываться в курсе. Но одновременно и одна из cамых важных.
Во всем мире Python часто используют для работы с данными. Объем данных может быть небольшим — такой сможет обработать и один слабый компьютер. Но данных может быть и наcтолько много, что потребуются целые вычислительные кластеры (так называют несколько компьютеров, объединенных в сеть и решающих общую задачу), ибо только такие мощности способны переварить подобные объемы информации.
Есть даже такая отрасль — data science , наука о данных. И Python — один из основных инструментов, которые применяются в данной сфере. Машинное обучение, экспертные системы, интеллектуальный анализ данных — со всем этим работают питонисты!
Любые данные нужно как-то представлять в памяти компьютера — и делать это нужно так, чтобы с данными было удобно и эффективно работать. В программах данные часто хранятся в коллекциях. Список пользователей, список страниц, список дат, список строк, список серверов — все эти сущности могут быть представлены в коде в виде коллекций. Python известен тем, что поставляется с набором готовых видов коллекций, которые работают очень эффективно и удобны в использовании. Как говорят, «батарейки входят в комплект». Вот основные встроенные типы коллекций в Python:
- Списки («lists»)
- Словари («dictionaries»)
- Множества/наборы («sets»)
Разные типы коллекций требуют разных подходов к использованию и полезны в разных ситуациях. Более того, существует несколько сильно различающихся подходов для работы с одними только списками! И настоящий питонист должен уметь понять, какую коллекцию нужно применить в нужный момент и каким способом с ней работать, какие преимущества даст тот или иной выбор и какими недостатками этот выбор будет обладать.
Еще важно понять, что обработка коллекций — во многом алгоритмическая история, и она просто так сама в голове не сформируется. Нужно развить понимание того, как программа будет выполняться, какие ресурсы затратит компьютер на ее выполнение. Именно поэтому коллекциям уделены сразу несколько курсов в рамках специализации. Но и в курсах, напрямую не связанных с обработкой данных с применением коллекций, они все равно будут широко использоваться. Таким образом вы сможете отточить свои навыки по работе с коллекциями: нужны время и задачки, чтобы появились необходимые связи в мозгу.
Важно также отметить, что навыки реализации даже простейших алгоритмов хорошо развивают и структурируют мышление. То есть эти курсы преследуют две цели:
- Научиться алгоритмически мыслить
- Научиться быстро решать типичные задачи по работе с коллекциями
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
Что такое коллекции в python
[Коллекции] Списки (массивы) в Python: описание, примеры использования, функции списков
02 марта 2023
Оценки статьи
Еще никто не оценил статью
Списки (или массивы) являются одним из основных типов данных в Python, который позволяет хранить упорядоченную коллекцию элементов разных типов. Списки могут быть изменяемыми (mutable), что позволяет добавлять, удалять и изменять элементы внутри списка. В этой статье мы рассмотрим основные функции и методы, которые доступны для работы со списками в Python.
Создание списков
Списки в Python создаются с помощью квадратных скобок []. Элементы списка разделяются запятой.
Например:
my_list = [1, 2, 3, 'four', 5.0]
В списке можно хранить элементы разных типов данных. В данном примере мы создали список из пяти элементов: трех чисел, строки и числа с плавающей точкой.
Также можно создать пустой список:
empty_list = []
Другие способы создания списков
Существуют и другие способы создания списков в Python. Например, список можно создать с помощью встроенной функции list() , которая преобразует любой итерируемый объект в список.
Например:
my_tuple = ('apple', 'banana', 'cherry') my_list = list(my_tuple)
Также, можно создать список с помощью генератора списка. Генератор списка — это выражение, которое создает список, заполняя его элементами в соответствии с заданными правилами. Генератор списка создается с помощью квадратных скобок и выражения, которое определяет элементы списка.
Например, чтобы создать список всех нечетных чисел от 1 до 10, можно использовать следующий генератор списка:
my_list = [x for x in range(1, 11) if x % 2 != 0]
Здесь мы используем функцию range() для создания списка чисел от 1 до 10, и затем фильтруем его с помощью условного выражения, чтобы оставить только нечетные числа.
Кроме того, список можно создать с помощью функции split() , которая разбивает строку на подстроки по заданному разделителю и возвращает список подстрок.
Например:
my_string = "apple,banana,cherry" my_list = my_string.split(",")
Здесь мы используем запятую в качестве разделителя, чтобы создать список из трех элементов: ‘apple’, ‘banana’ и ‘cherry’.
Тип данных списков
В Python списки являются изменяемыми (mutable) объектами, то есть их можно изменять после создания. Это означает, что вы можете добавлять, удалять или изменять элементы внутри списка. Также можно изменять длину списка.
Примеры изменения списка
Ниже приведены несколько примеров, которые демонстрируют работу со списками в Python.
my_list = [1, 2, 3] print(my_list) # [1, 2, 3] print(len(my_list)) # 3 my_list.append(4) print(my_list) # [1, 2, 3, 4] my_list.insert(0, 0) print(my_list) # [0, 1, 2, 3, 4] my_list.pop() print(my_list) # [0, 1, 2, 3] my_list.remove(2) print(my_list) # [0, 1, 3] my_list.reverse() print(my_list) # [3, 1, 0] my_list.sort() print(my_list) # [0, 1, 3]
В первой строке мы создали список из трех элементов, содержащий числа. Затем мы напечатали список и его длину с помощью функции len() .
Далее мы добавили элемент 4 в конец списка с помощью метода append() . Затем мы добавили элемент 0 в начало списка с помощью метода insert() .
Затем мы удалили последний элемент списка с помощью метода pop() . Мы также удалили элемент со значением 2 с помощью метода remove() .
Далее мы изменяем порядок элементов списка на обратный с помощью метода reverse() . Затем мы отсортировали элементы списка в порядке возрастания с помощью метода sort() .
Функции списков
В Python есть множество встроенных функций, которые можно использовать со списками. Некоторые из них:
- all() — возвращает True, если все элементы списка истинны, и False в противном случае
- any() — возвращает True, если хотя бы один элемент списка и один истинный, и False в противном случае
- len() — возвращает длину списка
- max() — возвращает наибольший элемент в списке
- min() — возвращает наименьший элемент в списке
- sum() — возвращает сумму всех элементов в списке
Некоторые другие полезные методы списков в Python:
- append() — добавляет элемент в конец списка
- clear() — удаляет все элементы списка
- copy() — создает копию списка
- count() — возвращает количество элементов с заданным значением
- extend() — добавляет элементы другого списка в конец текущего списка
- index() — возвращает индекс первого элемента с заданным значением
- insert() — вставляет элемент в список на заданную позицию
- pop() — удаляет и возвращает последний элемент списка, либо элемент с указанным индексом
- remove() — удаляет первый элемент с заданным значением
- reverse() — изменяет порядок элементов списка на обратный
- sort() — сортирует элементы списка в порядке возрастания
Заключение
Списки в Python являются одним из основных типов данных в языке, и они предоставляют множество возможностей для управления наборами данных.
Списки могут содержать элементы разных типов данных, их можно изменять после создания, и у них есть множество встроенных функций и методов, которые облегчают работу с ними. Списки широко используются в Python и полезны для различных задач программирования.
Меню категорий
-
Загрузка категорий.
Язык Python. Дополнительные типы коллекций
Коллекциями в языке Python принято называть типы данных, в том или ином виде хранящие ссылки на ряд других объектов (не обязательно однотипных). Коллекции делятся на последовательности, множества и отображения. Среди встроенных типов данных к первым относятся списки (тип данных list) и кортежи (tuple), ко вторым – обычные (изменяемые) и фиксированные множества (set и frozenset), и, наконец, к третьим – словари (dict).
Для большинства решаемых задач этих типов коллекций более чем достаточно, но иногда всё же возникает потребность в нестандартных типах. И по мере развития языка всё реже приходится прибегать к собственным реализациям, поскольку с каждым новым релизом стандартная библиотека Python предлагает всё больше дополнительных типов данных.
В данной статье мы рассмотрим типы коллекций, которые доступны в модуле collections стандартной библиотеки Python 3.1.
Класс collections.namedtuple позволяет создать тип данных, ведущий себя как кортеж, с тем дополнением, что каждому элементу («полю») присваивается имя, по которому можно в дальнейшем получать доступ к нему как к атрибуту:
>>> User = collections.namedtuple(‘User’, ‘name phone login speed’)
>>> vasya = User(‘Петров В. И.’, 22343, ‘vasya’, 128)
>>> for field in vasya:
>>> print(vasya[3]) # работает как обычный кортеж
vasya 128 |
>>> tvasya = tuple(vasya) # если нужен простой кортеж
(‘Петров В. И.’, 22343, ‘vasya’, 128) |
Первым параметром функции namedtuple() передаётся имя создаваемого типа данных, которое будет возвращаться функцией type() и фигурировать, например, в сообщениях об ошибках. Второй параметр – разделённый пробелами список «полей» в том порядке, как они будут следовать в кортеже. С помощью дополнительного аргумента rename=True (появился в Python 3.1) можно включить автоматическое переименование тех полей, для которых задано недопустимое с точки зрения Python имя (например, не соответствующее правилам именования идентификаторов или одно из зарезервированных слов) – такие поля автоматически получат имена вида _0, _1 и т.д., число соответствует порядковому номеру поля:
>>> Bool = collections.namedtuple(‘Bool’, ‘False True’, rename=True)
>>> test = Bool(‘2 > 3’, ‘7 < 8')
Bool(_0=’2 > 3′, _1=’7 < 8') |
Данный пример, конечно, искусственный. Реальная потребность в переименовании может понадобиться, если имена полей берутся из «внешних источников», например формируются на основании заголовка CSV-файла. Использование этого типа данных позволяет повысить удобочитаемость кода, поскольку не нужно постоянно вспоминать, какой смысл несёт значение под тем или иным индексом.
Раньше аналогичное поведение можно было получить, создав собственный класс с соответствующими атрибутами. Иногда, чтобы сделать код более понятным, использовался и такой приём:
NAME, PHONE, LOGIN, SPEED = (0, 1, 2, 3) # или range(4)
vasya = (‘ Петров В . И .’, 22343, ‘vasya’, 128)
Теперь всё доступно в стандартной библиотеке, и вам нет необходимости прикладывать лишние усилия.
Словари со значением по умолчанию
Рассмотрим небольшой пример:
>>> for dig in sample:
File «», line 2, in
Знакомая ситуация? Да, мы хотели в словаре counter посчитать число вхождений каждого элемента в списке sample. Но на первой же итерации возникла ошибка, так как словарь пуст и элемента с ключом 1 ещё нет – прибавлять единицу не к чему. В обычных словарях эта проблема решается либо предварительной проверкой на вхождение, либо с помощью методов словаря get() или setdefault(), либо обработкой соответствующего исключения:
if dig in counter:
counter[dig] = counter.get(dig, 0) + 1
counter[dig] = counter.setdefault(dig, 0) + 1
Однако в модуле collections стандартной библиотеки есть тип данных defaultdict, отличающийся от стандартного словаря как раз способностью автоматически создавать элементы для отсутствующих ключей:
for dig in sample:
Эта конструкция уже не вызовет никаких ошибок – если элемент с нужным ключом в словаре отсутствует, он будет создан автоматически, а значением по умолчанию будет результат выполнения «фабричной функции», переданной в качестве параметра при инициализации словаря. В качестве «фабричной» можно использовать любую функцию, возвращающую какое-либо значение. В нашем примере мы используем встроенную функцию int(), которая, будучи вызвана без аргумента, возвращает 0. Именно это значение и будет присвоено вновь создаваемому элементу.
Аналогично вы можете использовать собственную функцию (она должна уметь выполняться без аргументов) или lambda-функцию: collections.defaultdict(lambda: ‘default’) создаст словарь, в котором автоматически создаваемые элементы будут получать в качестве значения строку default. Учтите, что конструктору defaultdict() должна передаваться именно ссылка на функцию (то есть её имя), а не возвращаемое значение. Поэтому имя нужно указывать без скобок.
Только не увлекайтесь этим типом данных – иногда лучше получить ошибку исполнения из-за отсутствия ключа в словаре, чем логическую ошибку, которую будет гораздо сложнее отловить.
Тип deque позволяет очень просто имитировать такие последовательности, как очереди и стеки.
В объект fifo мы добавляем элементы слева, а извлекаем справа, реализуя тем самым очередь типа FIFO (First In – First Out, «первый пришёл – первый вышел»). Объект stack ведёт себя по принципу LIFO (Last In – First Out, «последний пришёл – первый вышел»). Хотя в принципе ничто не мешает добавлять и извлекать элементы с любой из сторон. Соблюдение соглашений здесь целиком и полностью ложится на программиста.
Объекты класса deque, как и другие коллекции, являются итерируемыми – при желании вы всегда можете выполнить их обход в цикле. Можно обращаться к элементам и по индексу.
По большому счёту, продемонстрированное выше поведение неплохо обеспечивается и обычным списком: методы append() и pop() ведут себя точно так же, а работу с началом списка можно реализовать методами pop(0) и insert(0), то есть передавая в качестве аргумента индекс извлекаемого элемента (кстати, метод pop() объектов deque «умеет» извлекать только последний элемент, а метода insert() нет вообще).
Хотя методы appendleft() и popleft() класса deque, на мой взгляд, более очевидны. Также скорость их выполнения не зависит от количества элементов в очереди (в терминах оценки времени исполнения алгоритмов O(), вставка и извлечение элементов как сначала очереди, так и с конца, имеет производительность O(1)) – например, при большом числе элементов метод appendleft() выполняется в разы быстрее, чем метод insert() для списков.
Но зато тип deque предоставляет метод rotate(N), переносящий N последних элементов в начало очереди (для отрицательного значения N – с начала в конец; по умолчанию N=1). Так, последовательно применяя этот метод к очереди deque([1, 2, 3, 4, 5]) , мы будем получать deque([5, 1, 2, 3, 4]) , deque([4, 5, 1, 2, 3]) и так далее. Как пример использования, можно привести реализацию «русской рулетки»:
import collections, random
for shot in range(len(baraban)):
input(‘Чья очередь — нажмите Enter. ‘)
print(‘Финита ля комедия, господа!’)
Класс OrderedDict появился в Python 3.1 и позволяет создавать словари с фиксированным порядком элементов. В стандартных словарях, как известно, порядок элементов не определён – они хранятся на основании хэш-функции, и любое изменение словаря может изменить и порядок, в котором элементы будут доступны при переборе (например, в цикле for . in).
Если же порядок заполнения словаря для реализуемого вами алгоритма важен, можете воспользоваться классом OrderedDict – он гарантирует, что при переборе элементы словаря будут возвращаться строго в том порядке, в каком в словарь помещались (аналогично спискам):
KeysView(OrderedDict([(‘w’, 123), (‘a’, 34)])) |
При обновлении значения элемента он остаётся на своём месте, если же элемент удалить и тут же добавить вновь, он попадёт в конец списка. С помощью этого типа данных удобно, например, вести подсчёт некоторых событий, если помимо их количества важно знать и порядок их возникновения.
Ещё один тип данных, появившийся в модуле collections в Python 3.1, – Counter. Чуть выше, когда мы обсуждали словари со значением по умолчанию, мы в качестве примера решали задачу подсчёта количества одинаковых элементов в некотором списке. Благодаря классу Counter (и разработчикам языка Python) это теперь можно сделать одной строчкой:
Counter() |
Столь же просто можно выполнить подсчёт любых элементов в любой последовательности, например посчитать частоту появления различных символов в файле (строка текста не вполне вписывается в понятие коллекции, поскольку является одним объектом, а не набором ссылок на другие, но везде, где подразумевается итерируемый объект, строка рассматривается как последовательность отдельных символов):
[(‘ ‘, 1162), (‘e’, 397), (‘s’, 284)] |
Метод most_common() возвращает указанное число наиболее часто встречающихся элементов, упакованных в кортежи (ключ, значение). Здесь «золото» взял пробел.
Как видите, в модуль collections добавлено уже довольно много типов «нестандартных» коллекций (а ведь ещё в версии 2.5 там были представлены только defaultdict и deque), которые могут в ряде случаев заметно упростить вашу программу и сделать её более понятной. Помимо рассмотренных «готовых к употреблению» типов данных, модуль collections предоставляет и ряд абстрактных классов и «классов-заготовок», на базе которых вы можете создавать свои собственные типы коллекций.
Подробную документацию к модулю collections вы найдёте по следующей ссылке: http://docs.python.org/3.1/library/collections.html. Также обратите внимание на модули array, queue и heapq – в ряде случаев они могут предоставить более соответствующие вашим задачам специализированные типы данных.
Встроенные типы коллекций
Кратко напомню основные особенности встроенных коллекций:
Список (list) – тип данных, хранящий упорядоченный список ссылок на другие объекты (элементы списка). Обычно создается с использованием квадратных скобок: [1, ‘два’, 3]. (Замечание: помимо приведённого здесь и далее синтаксиса, объект любого типа данных в Python может быть создан вызовом соответствующей (одноимённой имени типа) функцией. Например, int(5) создаст целое число со значением 5, list() создаст пустой список, и т.д.)
Кортеж (tuple) – неизменяемый набор элементов. Создается с использованием круглых скобок: (1, ‘два’, 3). В отличие от списка, кортеж представляет из себя единый объект, состоящий из нескольких элементов, и соответственно элементы нельзя изменять, удалять, добавлять иначе, как путём создания нового объекта. Благодаря неизменяемости операции с кортежем выполняются несколько быстрее, чем со списком, и его можно использовать там, где требуется «хэшируемый» объект, например, ключ словаря (см. далее).
Множество (set) – неупорядоченный список уникальных элементов. Создается с использованием фигурных скобок: ; пустое множество можно создать только вызовом функции set(). Все дублирующиеся элементы удаляются. Элементами могут быть только хэшируемые (неизменяемые) объекты – числа, строки, кортежи, фиксированные множества (frozenset). Благодаря использованию хэш-функции множества поддерживают очень быструю проверку на вхождение элемента оператором in (в списках и кортежах оператор in работает методом прямого перебора). Множества (как «обычные», так и фиксированные, о которых речь идёт в следующем абзаце) по своему поведению аналогичны математическим множествам и поддерживают методы, реализующие основные операции над ними – объединение, пересечение, разность, проверка на включение и т.д.
Фиксированное множество (frozenset) – неизменяемое множество (создаётся только вызовом функции frozenset()). Благодаря неизменяемости операции с ними выполняются ещё быстрее, и их можно использовать там, где требуется хэшируемый тип данных (как элементы множеств или ключи словарей).
Словарь (dict) – тип данных, хранящий пары «ключ – значение». Создается с использованием фигурных скобок: . Ключами могут быть только хэшируемые объекты, значениями – объекты любых типов. Порядок следования элементов не определён.
Затронем и один «тонкий» вопрос реализации языка Python – копирование объектов. С «бытовой» точки зрения присваивание «b = a» должно бы породить объект b, являющийся копией a. Но на практике мы видим совсем другое:
[1, 2, 5] |
[1, 2, 5] |
True |
Почему так происходит? Дело в том, что имя переменной содержит ссылку на объект (можно сказать, его адрес). Записывая «b = a», мы копируем в переменную b этот адрес, но все обращения по нему ведут к тому же объекту (обратите внимание, что выражение «a is b» возвращает True).
С неизменяемыми объектами – числами, строками, кортежами — этого не происходит, поскольку при любом «изменении» такого объекта фактически создаётся новый, и переменная b начинает указывать на него, в то время как a продолжает ссылаться на первоначальный объект.
Так как же создать копию изменяемой коллекции? Есть три основных способа: использование «полного» среза (b = a[:]), явное создание нового объекта на базе существующего (b = list(a)) и использование функции copy модуля copy (b = copy.copy(a)).
Всё это относится к так называемому «поверхностному» копированию – например, если копируемый список содержит вторым элементом словарь (точнее, ссылку на словарь), то список-копия будет ссылаться на тот же самый словарь. В итоге изменения в списках a и b не будут влиять друг на друга, а вот изменения в словаре a[1] будут видны и по ссылке b[1]. Чтобы создать абсолютно независимые копии, применяется «глубокое копирование», выполняемое функцией copy.deepcopy().
Коллекции в Python
Collections — это встроенный модуль Python, предоставляющий такие полезные типы данных, как контейнеры.
Контейнерные типы данных позволяют нам хранить и получать доступ к значениям удобным способом. Как правило, мы используем списки, кортежи и словари. Но при работе со структурированными данными нам нужны более умные объекты.
Сегодня мы разберем различные структуры данных, поддерживаемые модулем collections , и на примерах рассмотрим, когда их стоит использовать.
Содержание
- Именованный кортеж namedtuple
- Что такое именованный кортеж
- Альтернативный способ создания namedtuple
- Зачем использовать namedtuple вместо обычного словаря
- Как создать namedtuple из словаря в Python
- Как заменить атрибут в именованном кортеже
- Что происходит, когда вы удаляете и повторно вставляете ключи в OrderedDict
- Сортировка с помощью OrderedDict
- Что происходит, когда у нас есть избыточные ключи в ChainMap
- Как добавить новый словарь в ChainMap
- Как изменить порядок словарей в ChainMap
Итак, давайте приступать! Однако сначала нам обязательно нужно импортировать collections :
# Import the collections module import collections
Именованный кортеж namedtuple
Что такое именованный кортеж?
namedtuple можно представить как расширенную версию обычного кортежа tuple либо как быстрый способ создать класс с определенными именованными атрибутами.
Ключевое различие между кортежем и именованным кортежем заключается в следующем. Кортеж позволяет вам обращаться к данным через индексы, а с именованным кортежем вы можете получить доступ к элементам непосредственно по их именам.
Фактически вы можете определить, какие атрибуты может содержать именованный кортеж, и создать несколько его экземпляров. Точно так же, как вы поступили бы с классами.
Таким образом, с точки зрения функциональности он больше похож на класс, хотя и называется кортежем.
Давайте создадим namedtuple , который представляет из себя фильм movie с такими атрибутами, как жанр ( genre ), рейтинг ( rating ) и ведущий актер ( lead_actor ).
# Creating a namedtuple. # The field values are passed as a string seperated by ' ' from collections import namedtuple movie = namedtuple('movie','genre rating lead_actor') # Create instances of movie ironman = movie(genre='action',rating=8.5,lead_actor='robert downey junior') titanic = movie(genre='romance',rating=8,lead_actor='leonardo dicaprio') seven = movie(genre='crime',rating=9,lead_actor='Brad Pitt')
Теперь мы можем получить доступ к любой информации о нашем фильме, используя идентификатор. Это довольно быстро и удобно.
# Access the fields print(titanic.genre) print(seven.lead_actor) print(ironman.rating) # Вывод: # romance # Brad Pitt # 8.5
Альтернативный способ создания namedtuple
В качестве альтернативы вы можете передать список, состоящий из имен полей, вместо просто имен полей, разделенных пробелом.
К примеру, это может выглядеть так:
# Creating namedtuple by passing fieldnames as a list of strings book = namedtuple('book',['price','no_of_pages','author']) harry_potter = book('500','367','JK ROWLING') pride_and_prejudice = book('300','200','jane_austen') tale = book('199','250','christie') print('Price of pride and prejudice is ',pride_and_prejudice.price) print('author of harry potter is',harry_potter.author) # Вывод: # Price of pride and prejudice is 300 # author of harry potter is JK ROWLING
Доступ к элементам в namedtuple возможен как по индексу, так и по идентификатору.
print(tale[1]) # Вывод: # 250
Зачем использовать namedtuple вместо обычного словаря
Основным преимуществом namedtuple является то, что он занимает меньше места (памяти), чем аналогичный словарь.
Поэтому, в случае больших данных именованные кортежи эффективны.
# Create a dict and namedtuple with same data and compare the size import random import sys # Create Dict dicts = print('Size or space occupied by dictionary',sys.getsizeof(dicts)) # converting same dictionary to a namedtuple data=namedtuple('data',['numbers_1','numbers_2']) my_namedtuple= data(**dicts) print('Size or space occupied by namedtuple',sys.getsizeof(my_namedtuple)) # Вывод: # Size or space occupied by dictionary 240 # Size or space occupied by namedtuple 64
Выполняя приведенный выше код, вы обнаружите, что namedtuple имеет размер 64 байта, тогда как словарь занимает гораздо больше — 240 байт. Это почти в 4 раза больше памяти.
А теперь представьте себе эффект при обработке большого количества таких объектов. В общем, с целью экономии памяти гораздо лучше использовать именованные кортежи.
Как создать namedtuple из словаря в Python
Вы заметили, как мы преобразовали словарь в именованный кортеж с помощью оператора ** ?
Все, что вам нужно сделать для этого — определить структуру namedtuple и передать словарь ( **dict ) этому именованному кортежу в качестве аргумента. Единственное требование заключается в том, что ключи словаря должны совпадать с именами полей namedtuple .
# Convert a dictionary into a namedtuple dictionary=dict() # Convert book = namedtuple('book',['price','no_of_pages','author']) print(book(**dictionary)) # Вывод: # book(price=567, no_of_pages=878, author='cathy thomas')
Как заменить атрибут в именованном кортеже
Что делать, если значение одного атрибута необходимо изменить?
Вам нужно обновить его в данных. Для этого просто воспользуемся методом ._replace() :
# update the price of the book my_book=book('250','500','abc') my_book._replace(price=300) print("Book Price:", my_book.price) # Вывод: # Book Price: 250
Counter
Объект counter предоставляется библиотекой collections . Давайте поподробнее разберем, что он собой представляет.
К примеру, у вас есть список каких-то случайных чисел. Что, если вы хотите узнать, сколько раз встречается каждое число?
Счетчик counter позволяет легко вычислить частоту. Он работает не только с числами, но и с любым итерируемыми объектами, такими как строки и списки.
Counter — это подкласс dict , используемый для подсчета хешируемых объектов.
Он возвращает словарь с элементами в качестве ключей и “счетчиком” (количество вхождений элемента) в качестве значений.
Примеры
Теперь давайте разберем некоторые примеры.
#importing Counter from collections from collections import Counter numbers = [4,5,5,2,22,2,2,1,8,9,7,7] num_counter = Counter(numbers) print(num_counter) # Вывод: # Counter()
Давайте используем счетчик counter , чтобы найти частоту вхождений каждого символа в строке.
#counter with strings string = 'lalalalandismagic' string_count = Counter(string) print(string_count) # Вывод: # Counter()
Как мы видим, counter позволяет посмотреть, какие элементы есть в строке и сколько их.
Усложним задачу. Допустим, у вас есть предложение и вы хотите посмотреть количество слов в нем. Как это сделать?
При помощи функции split() можно составить список слов в предложении и передать его в Counter() .
# Using counter on sentences line = 'he told her that her presentation was not that good' list_of_words = line.split() line_count=Counter(list_of_words) print(line_count) # Вывод: # Counter()
Как найти наиболее частотные элементы с помощью счетчика
Счетчик очень полезен в реальных приложениях. Особенно, когда вам нужно обработать большие данные, и вы хотите узнать частотность некоторых элементов. Давайте рассмотрим несколько очень полезных методов, использующих counter .
Такое выражение возвращает список « n наиболее распространенных элементов» вместе с их количеством в порядке убывания.
# Passing different values of n to most_common() function print('The 2 most common elements in `numbers` are', Counter(numbers).most_common(2)) print('The 3 most common elements in `string` are', Counter(string).most_common(3)) # Вывод: # The 2 most common elements in `numbers` are [(2, 3), (5, 2)] # The 3 most common elements in `string` are [('a', 5), ('l', 4), ('i', 2)]
Метод most_common() можно использовать для вывода наиболее часто повторяющегося элемента. Используется в частотном анализе.
print(Counter(list_of_words).most_common(1)) # Вывод: # [('her', 2)]
Этот же метод можно использовать для поиска наиболее частотного символа в строке.
print(Counter(string).most_common(3)) # Вывод: # [('a', 5), ('l', 4), ('i', 2)]
Что произойдет, если вы не укажете n при использовании most_common(n) ?
Тогда все элементы с их количеством вхождений будут напечатаны в порядке убывания количества.
print(Counter(string).most_common()) # Вывод: # [('a', 5),('l', 4),('i', 2),('n', 1),('d', 1),('s', 1),('m', 1),('g', 1),('c', 1)]
Еще есть метод Counter().elements() , который возвращает все элементы, количество которых больше 0.
print(sorted(string_count.elements())) # Вывод: # ['a', 'a', 'a', 'a', 'a', 'c', 'd', 'g', 'i', 'i', 'l', 'l', 'l', 'l', 'm', 'n', 's']
Defaultdict
Словарь представляет из себя неупорядоченный набор ключей и значений.
В парах ключ:значение ключи должны быть уникальны и неизменяемы. Поэтому список не может быть ключом словаря, так как он изменяемый. А вот кортеж может.
# Dict with tuple as keys: OKAY <('key1', 'key2'): "value"># Dict with list as keys: ERROR
Чем defaultdict отличается от простого словаря?
Если вы попытаетесь получить доступ к ключу, которого нет в словаре, он выдаст ошибку KeyError . В то время как при использовании defaultdict такой ошибки не будет.
Если вы попробуете обратиться к отсутствующему ключу, defaultdict просто вернет значение по умолчанию.
Синтаксис будет следующим: defaultdict(default_factory) .
При обращении к отсутствующему ключу функция default_factory вернет значение по умолчанию.
# Creating a defaultdict and trying to access a key that is not present. from collections import defaultdict def_dict = defaultdict(object) def_dict[‘fruit’] = ‘orange’ def_dict[‘drink’] = ‘pepsi’ print(def_dict[‘chocolate’]) # Вывод: #
При запуске этого кода вы не получите KeyError .
Если вы хотите вывести сообщение о том, что значение запрошенного ключа отсутствует, можно определить собственную функцию и передать ее в defaultdict .
К примеру, это может выглядеть так:
# Passing a function to return default value def print_default(): return 'value absent' def_dict=defaultdict(print_default) print(def_dict['chocolate']) # Вывод: # value absent
Во всем остальном defaultdict ничем не отличается от обычного словаря. Синтаксис команд полностью идентичен.
Вы также можете обойти ошибку KeyError и при использовании обычного словаря — с помощью метода get() .
# Make dict return a default value mydict = print(mydict.get('c', 'NOT PRESENT')) # Вывод: # NOT PRESENT
OrderedDict
Словарь — это НЕупорядоченная коллекция пар ключ-значение. Однако OrderedDict поддерживает упорядочивание ключей.
Это в некотором роде подкласс словаря dict .
Давайте создадим обычный словарь и сделаем его OrderedDict , чтобы показать, в чем заключается разница.
# create a dict and print items vehicle = print('This is normal dict') for key,value in vehicle.items(): print(key,value) print('-------------------------------') # Create an OrderedDict and print items from collections import OrderedDict ordered_vehicle=OrderedDict() ordered_vehicle['bicycle']='hercules' ordered_vehicle['car']='Maruti' ordered_vehicle['bike']='Harley' print('This is an ordered dict') for key,value in ordered_vehicle.items(): print(key,value) # Вывод: # This is normal dict # bicycle hercules # car Maruti # bike Harley # scooter bajaj ------------------------------- # This is an ordered dict # bicycle hercules # car Maruti # bike Harley
В OrderedDict даже после изменения значения некоторых ключей порядок остается прежним.
# I have changed the value of car in this ordered dictionary. ordered_vehicle['car']='BMW'# I have changed the value of car in this ordered dictionary. for key,value in ordered_vehicle.items(): print(key,value) # Вывод: # bicycle hercules # car BMW # bike harley davison
Что происходит, когда вы удаляете и повторно вставляете ключи в OrderedDict
При удалении ключа информация о его порядке также удаляется. Когда вы повторно вставляете ключ, он обрабатывается как новая запись и соответствующая информация сохраняется.
# deleting a key from an OrderedDict ordered_vehicle.pop('bicycle') for key,value in ordered_vehicle.items(): print(key,value) # Вывод: # car BMW # bike harley davison
При повторной вставке ключа запись считается новой.
# Reinserting the same key and print ordered_vehicle['bicycle']='hercules' for key,value in ordered_vehicle.items(): print(key,value) # Вывод: # car BMW # bike harley davison # bicycle hercules
Вы видите, что bicycle находится в конце, так как порядок изменился, когда мы удалили ключ.
Есть несколько полезных команд, которые можно использовать с OrderedDict. К примеру, мы можем выполнять функции сортировки.
Сортировка с помощью OrderedDict
Сортировка элементов, например, по возрастанию значений, может помочь в анализе данных. Давайте посмотрим, что мы можем сделать.
- Сортировка элементов по ключу KEY (в порядке возрастания):
# Sorting items in ascending order of their keys drinks = OrderedDict(sorted(drinks.items(), key=lambda t: t[0])) # Вывод: # OrderedDict([('apple juice', 2), ('coke', 5), ('pepsi', 10)])
- Сортировка пар по значению VALUE (в порядке возрастания):
# Sorting according to values OrderedDict(sorted(drinks.items(), key=lambda t: t[1])) # Вывод: # OrderedDict([('apple juice', 2), ('coke', 5), ('pepsi', 10)])
- Сортировка словаря по длине строки ключа (в порядке возрастания):
# Sorting according to length of key string OrderedDict(sorted(drinks.items(), key=lambda t: len(t[0]))) # Вывод: # OrderedDict([('coke', 5), ('pepsi', 10), ('apple juice', 2)])
ChainMap
ChainMap — это контейнерный тип данных, в котором хранится несколько словарей.
Если у вас несколько связанных или похожих словарей, зачастую их можно хранить вместе, в ChainMap .
Распечатать все элементы ChainMap можно при помощи .map :
# Creating a ChainMap from 3 dictionaries. from collections import ChainMap dic1= dic2= dic3= my_chain = ChainMap(dic1,dic2,dic3) my_chain.maps # Вывод: # [, ,]
Также мы можем вывести ключи всех словарей, используя функцию .keys() :
print(list(my_chain.keys())) # Вывод: # ['firstname', 'lastname', 'chennai', 'delhi', 'red', 'black', 'white']
Можно получить и значения всех словарей в ChainMap — при помощи функции .values() .
print(list(my_chain.values())) # Вывод: # ['bob', 'mathews', 'tamil', 'hindi', 5, 1, 2]
Что происходит, когда у нас есть избыточные ключи в ChainMap?
Возможно, что 2 словаря содержат один и тот же ключ. К примеру, как это показано ниже:
# Creating a chainmap whose dictionaries do not have unique keys dic1 = dic2 = chain = ChainMap(dic1,dic2) print(list(chain.keys())) # Вывод: # ['black', 'red', 'white']
Обратите внимание, что red не повторяется, он печатается только один раз.
Как добавить новый словарь в ChainMap?
Вы можете добавить новый словарь в начало ChainMap , используя метод .new_child() .
# Add a new dictionary to the chainmap through .new_child() print('original chainmap', chain) new_dic= chain=chain.new_child(new_dic) print('chainmap after adding new dictioanry',chain) # Вывод: # original chainmap ChainMap(, ) # chainmap after adding new dictioanry ChainMap(, , )
Как изменить порядок словарей в ChainMap?
Порядок, в котором словари хранятся в ChainMap , можно изменить с помощью функции reversed() .
# We are reversing the order of dictionaries using reversed() function print('orginal chainmap', chain) chain.maps = reversed(chain.maps) print('reversed Chainmap', str(chain)) # Вывод: # orginal chainmap ChainMap(, , ) # reversed Chainmap ChainMap(, , )
UserList
Надеюсь, вы знакомы со списками в Python. Если нет, то почитать о них подробнее можно в статье «Списки в Python: полное руководство для начинающих».
UserList — это похожий на список контейнерный тип данных, который является классом-оболочкой для списков.
Синтаксис будет следующим: collections.UserList([list]) .
Вы передаете обычный список в качестве аргумента userlist . Этот список хранится в атрибуте ‘data’ и доступен через метод UserList.data .
# Creating a user list with argument my_list from collections import UserList my_list=[11,22,33,44] # Accessing it through `data` attribute user_list=UserList(my_list) print(user_list.data) # Вывод: # [11, 22, 33, 44]
В чем польза UserLists?
Предположим, вы хотите удвоить все элементы в определенных списках. Или, может быть, вы хотите убедиться, что ни один элемент не может быть удален из заданного списка.
В таких случаях нам нужно добавить в наши списки определенное «поведение», что можно сделать с помощью UserLists .
Давайте рассмотрим, как можно использовать UserList для переопределения функциональности встроенного метода. Приведенный ниже код предотвращает добавление нового значения в список:
# Creating a userlist where adding new elements is not allowed. class user_list(UserList): # function to raise error while insertion def append(self,s=None): raise RuntimeError("Authority denied for new insertion") my_list=user_list([11,22,33,44]) # trying to insert new element my_list.append(55)
#> --------------------------------------------------------------------------- RuntimeError Traceback (most recent call last) in 4 5 my_list=user_list([11,22,33,44]) ----> 6 my_list.append(55) 7 print(my_list) <ipython-input-2-e8f22159f6e0> in append(self, s) 1 class user_list(UserList): 2 def append(self,s=None): ----> 3 raise RuntimeError("Authority denied for new insertion") 4 5 my_list=user_list([11,22,33,44]) RuntimeError: Authority denied for new insertion
Код выводит сообщение RunTimeError и не позволяет добавить элемент в список. Это может быть полезно, если вы хотите не допустить внесения информации после определенного срока.
UserString
Подобно тому, как UserLists является классом-оболочкой для списков, UserString является классом-оболочкой для строк.
UserString позволяет добавлять к строке определенное поведение. Вы можете передать этому классу любой конвертируемый в строку аргумент и затем получить доступ к этой строке, используя атрибут data.
# import Userstring from collections import UserString num=765 # passing an string convertible argument to userdict user_string = UserString(num) # accessing the string stored user_string.data # Вывод: # '765'
Как видите, число 765 было преобразовано в строку «765» , и доступ к ней можно получить с помощью метода UserString.data .
Как и когда можно использовать UserString
UserString можно использовать для изменения строк или выполнения определенных функций.
Предположим, вы хотите удалить определенное слово из текстового файла (где бы оно ни было). Возможно, некоторые слова в тексте неуместны.
Давайте посмотрим на пример того, как UserString можно использовать для удаления определенных слов из строки.
# Using UserString to remove odd words from the textfile class user_string(UserString): def append(self, new): self.data = self.data + new def remove(self, s): self.data = self.data.replace(s, "") text='apple orange grapes bananas pencil strawberry watermelon eraser' fruits = user_string(text) for word in ['pencil','eraser']: fruits.remove(word) print(fruits) # Вывод: # apple orange grapes bananas strawberry watermelon
В этом примере pencil и eraser были удалены с помощью функционального класса user_string .
Рассмотрим другой случай. Что делать, если вам нужно заменить слово другим во всем файле?
При помощи UserString сделать это просто. Мы определили функцию внутри класса, чтобы заменить определенное слово на The Chairman во всем тексте.
# using UserString to replace the name or a word throughout. class user_string(UserString): def append(self, new): self.data = self.data + new def replace(self,replace_text): self.data = self.data.replace(replace_text,'The Chairman') text = 'Rajesh concluded the meeting very late. Employees were disappointed with Rajesh' document = user_string(text) document.replace('Rajesh') print(document.data) # Вывод: # The Chairman concluded the meeting very late. Employees were disappointed with The Chairman
Как видите, слово Rajesh везде заменено на The Chairman .
UserDict
Это класс-оболочка для словарей. Его синтаксис аналогичен UserList и UserString .
Мы передаем словарь в качестве аргумента, который хранится в атрибуте ‘data’.
# importing UserDict from collections import UserDict my_dict= # Creating an UserDict user_dict = UserDict(my_dict) print(user_dict.data) # Вывод: #
Как можно использовать UserDict
UserDict позволяет нам создать словарь и модифицировать его под наши нужды. Давайте посмотрим на пример того, как UserDict можно использовать для переопределения функциональности встроенного метода. Приведенный ниже код предотвращает удаление пары ключ-значение.
# Creating a Dictionary where deletion of an is not allowed class user_dict(UserDict): # Function to stop delete/pop def pop(self, s = None): raise RuntimeError("Not Authorised to delete") data = user_dict() # try to delete a item data.pop(1)
#> --------------------------------------------------------------------------- RuntimeError Traceback (most recent call last) in 12 13 #try to delete a item ---> 14 data.pop(1) in pop(self, s) 5 def pop(self, s = None): 6 ----> 7 raise RuntimeError("Not Authorised to delete") 8 9 RuntimeError: Not Authorised to delete
Вы получите сообщение RunTimeError . Это может помочь, если вы не хотите потерять данные.
Что делать, если некоторые ключи имеют ненужные значения, и вам нужно заменить их на null или 0? Эту проблему можно решить следующим образом:
class user_dict(UserDict): def replace(self,key): self[key]=’0′ file= user_dict() # Delete ‘blue’ and ‘yellow’ for i in [‘blue’,’yellow’]: file.replace(i) print(file) # Вывод: #
Поле с ненужными значениями заменено на 0. И это лишь простые примеры того, как UserDict позволяет создать словарь с необходимой функциональностью.
Заключение
Итак, мы разобрали основные типы контейнерных данных с примерами. Они значительно повышают эффективность работы при использовании на больших наборах данных.
Надеемся, данная статья была вам полезна! Успехов в написании кода!