Как создать копию списка в оперативной памяти
Электронные таблицы Excel - это интуитивно понятный и удобный способ манипулирования большими наборами данных без какой-либо предварительной технической подготовки. По этому, это один из форматов, с которым, в какой-то момент времени, вам придется иметь дело. Часто будут стоять задачи по извлечению каких-то данных из базы данных или файла логов в электронную таблицу Excel, или наоборот, преобразовывать электронную таблицу Excel в какую-либо более удобную программную форму, примеров этому масса.
Модуль openpyxl - это библиотека Python для чтения/записи форматов Office Open XML (файлов Excel 2010) с расширениями xlsx / xlsm / xltx / xltm .
Преобразование списка в словарь
Преобразовать список в словарь можно при помощи метода dict.fromkeys() , генераторов словарей или метода zip() . Метод zip() полезен, если вы хотите объединить два списка в словарь.
Давайте вкратце разберем эти методы:
- dict.fromkeys() : используется для создания словаря из списка. При желании можно установить значение по умолчанию для всех ключей. При этом вы не можете установить индивидуальные значения для каждого элемента в словаре.
- Генератор словарей: создает новый словарь из существующего списка. Вы можете указать разные значения для каждого ключа в словаре. Генератор словаря по своей структуре похож на генератор списков.
- zip() : преобразует два (или больше) списка в список кортежей. Для преобразования этого списка кортежей в словарь можно использовать метод dict() .
Давайте применим каждый из этих трех методов, чтобы на примерах разобрать преобразование списка в словарь.
Поверхностное копирование
Поверхностное копирование создает отдельный новый объект или список, но вместо копирования дочерних элементов в новый объект, оно просто копирует ссылки на их адреса памяти. Следовательно, если вы сделаете изменение в исходном объекте, оно будет отражено в скопированном объекте, и наоборот.
Пример поверхностного копирования:
Старый список и новый список — разные объекты. Чтобы это доказать, давайте изменим старый список:
В этом примере мы создали поверхностную копию old_list. Новый список (new_list) содержит ссылки на исходные вложенные объекты, хранящиеся в старом списке. Когда мы добавили новый вложенный объект в old_list, это не отразилось на new_list, потому что в последнем не было ссылки на этот новый вложенный объект.
Давайте теперь попробуем изменить один из вложенных объектов, ссылки на которые были скопированы в new_list.
Изменения затронули оба списка, потому что оба они содержат ссылки на один и тот же вложенный объект.
Заключение
В этой статье мы разобрали, что такое генератор списков, в чем его преимущества и когда следует его использовать. Также мы увидели, насколько просто и легко читается генератор списков, а также насколько он компактнее и быстрее цикла for .
Мы также узнали, как написать генератор списка с условием или без него, с вложенными if и else и с вложенным циклом for .
Основы работы с файлами Microsoft Excel на Python.
Загрузка документа XLSX из файла.
Чтобы открыть существующую книгу Excel необходимо использовать функцию openpyxl.load_workbook() :
Есть несколько флагов, которые можно использовать в функции openpyxl.load_workbook() .
Следует сразу сказать, что оператор присваивания = не создаёт копию объекта. Присваивание создаёт новую переменную, которая дублирует ссылку на исходный объект.
Для примера давайте создадим из старого списка новый список (путем присваивания).
Вывод будет следующим:
Мы видим, что у обеих переменных — old_list и new_list — один id (140673303268168). Если внести изменения в любой из этих список, изменятся оба. Но иногда нам нужно создать копию самого объекта, а не копию ссылки на него.
Для копирования объектов в Python используется модуль copy и следующие методы:
- copy() . Копирует объект и возвращает поверхностную копию передаваемого аргумента.
- deepcopy() . Тоже копирует объект, но возвращает полную копию передаваемого аргумента.
Установка модуля openpyxl в виртуальное окружение.
Модуль openpyxl размещен на PyPI, поэтому установка относительно проста.
Списки и словари в Python
Списки и словари являются примерами коллекций Python. С их помощью мы можем хранить несколько (или даже много) похожих значений вместе, в одной структуре данных.
Список позволяет хранить данные в определенном порядке. Вот пример списка в Python:
Наш список takeout_prices содержит четыре значения.
А словари, в отличие от списков, не упорядочены.
Вот пример словаря в Python:
Словари полезны, если вы хотите связать каждое значение с какой-нибудь меткой — ключом. А если вы храните похожие значения, например, цены или имена, которым не можете назначить уникальные ключи, лучше использовать списки.
Циклы vs. генератор списков
Выше мы видели, как генератор списков позволяет выполнять задачу всего в одну строчку, в то время как цикл for требует написания нескольких строк.
Генератор списков не только более компактен, но также его эффективность выше. В некоторых случаях он оказывается в два раза быстрее, чем цикл for .
Английский для программистов
Наш телеграм канал с тестами по английскому языку для программистов. Английский это часть карьеры программиста. Поэтому полезно заняться им уже сейчас
Английский для программистов
Наш телеграм канал с тестами по английскому языку для программистов. Английский это часть карьеры программиста. Поэтому полезно заняться им уже сейчас
В Python вы можете преобразовать список в словарь, используя dictionary comprehension (генераторы словарей), dict.fromkeys() или метод zip() . Все эти три метода создают новый словарь. Они не изменяют существующий список.
Списки и словари в Python – это две структуры, используемые для хранения данных. Но что, если нам нужно преобразовать список в словарь? Вам это может понадобиться, если вы захотите присвоить уникальную метку каждому сохраненному вами значению. А это возможно только в словаре.
В Python есть несколько способов преобразовать список в словарь и несколько встроенных функций, которые можно использовать с этой целью. В этой статье мы рассмотрим все эти преобразования на примерах.
Когда использовать генератор списков (а когда его лучше избегать)
Вы можете использовать генератор списков, если выполняете простую фильтрацию, модификации или форматирование итерируемых объектов. Он также будет хорошим выбором, если вы хотите, чтобы ваш код был компактным и читабельным.
Кроме того, вы можете использовать генератор, когда для вас важно даже небольшое увеличение производительности.
Однако следует избегать использования генератора списков, если вам нужно добавить слишком много условий для фильтрации или модификации, поскольку это сделает ваш код излишне сложным и трудным для чтения.
Примечание редакции Pythonist: узнать больше об использовании генераторов списков можно в статье «Когда использовать List Comprehension в Python».
Получение только значений ячеек активного листа.
Если просто нужны значения из рабочего листа, то можно использовать свойство активного листа Worksheet.values . Это свойство перебирает все строки на листе, но возвращает только значения ячеек:
Для возврата только значения ячейки, методы Worksheet.iter_rows() и Worksheet.iter_cols() , представленные выше, могут принимать аргумент values_only :
Чем отличаются глубокое и поверхностное копирование?
Операции неглубокого и глубокого копирования объектов.
Операторы присваивания в Python не копируют объекты, они создают привязки между целью и объектом. Для коллекций, которые являются изменяемыми или содержат изменяемые элементы, иногда требуется копия, чтобы можно было изменить одну копию, не изменяя другую. Модуль copy обеспечивает общие операции неглубокого и глубокого копирования.
Конвертируем два списка в словарь при помощи zip()
В нашем последнем примере мы преобразовываем в словарь один список и присваиваем одинаковое значение по умолчанию для каждого ключа в словаре. Но можно преобразовать в словарь и два списка. Давайте попробуем это сделать.
Для этого мы можем использовать такую функцию Python, как zip(). Она позволяет объединить два списка. Элементы одного списка мы можем использовать в качестве ключей для словаря, а элементы второго — в качестве значений.
Итак, предположим, что у нас есть два списка: один содержит названия фруктов, а другой – их цены. Мы хотим создать единый словарь, в котором будет храниться название фрукта и его цена.
Для выполнения этой задачи мы можем использовать следующий код:
Запустим наш код и получим следующее:
Что же мы сделали? Во-первых, мы определили два списка: список фруктов fruits и список цен prices .
Затем мы использовали функцию zip() , чтобы объединить наши списки. Эта функция возвращает список кортежей. Поскольку нам нужен словарь, для преобразования наших кортежей мы использовали dict() .
В конце мы вывели содержимое нашего нового словаря в консоль.
Доступ к диапазону ячеек листа электронной таблицы.
Диапазон с ячейками активного листа электронной таблицы можно получить с помощью простых срезов. Эти срезы будут возвращать итераторы объектов ячеек.
Аналогично можно получить диапазоны имеющихся строк или столбцов на листе:
Можно также использовать метод Worksheet.iter_rows() :
Точно так же метод Worksheet.iter_cols() будет возвращать столбцы:
Примечание. Из соображений производительности метод Worksheet.iter_cols() недоступен в режиме только для чтения.
Если необходимо перебрать все строки или столбцы файла, то можно использовать свойство Worksheet.rows :
или свойство Worksheet.columns :
Примечание. Из соображений производительности свойство Worksheet.columns недоступно в режиме только для чтения.
Описание модуля copy .
Разница между мелким и глубоким копированием актуальна только для составных объектов, содержащих другие объекты, например списки или экземпляры классов:
- Неглубокая копия создает новый составной объект, а затем (насколько это возможно) вставляет в него ссылки на объекты, найденные в оригинале.
- Глубокая копия создает новый составной объект, а затем рекурсивно вставляет в него копии объектов, найденных в оригинале.
При операциях глубокого копирования часто возникают две проблемы, которых нет при операциях поверхностного копирования:
- Рекурсивные объекты (составные объекты, которые прямо или косвенно содержат ссылку на самих себя) могут вызвать рекурсивный цикл.
- Поскольку глубокая копия копирует все, она может копировать слишком много, например данные, которые предназначены для совместного использования между копиями.
Функция copy.deepcopy() позволяет избежать этих проблем:
-
ведет memo-словарь объектов, уже скопированных во время текущего прохода копирования;
позволяет пользовательским классам переопределять операцию копирования или набор копируемых компонентов.
Модуль copy не копирует такие типы, как модуль, метод, трассировка стека, кадр стека, файл, сокет, окно, массив или любые подобные типы. Он “копирует" функции и классы (неглубоко и глубоко), возвращая исходный объект без изменений, что совместимо с тем, как они обрабатываются модулем pickle .
Неглубокие копии словарей можно сделать с помощью метода dict.copy() , а списков - назначив срез всего списка, например copied_list = original_list[:] .
Чтобы класс мог определить свою собственную реализацию копии, он может определять специальные методы __copy__() и __deepcopy__() .
- Первый вызывается для реализации операции поверхностного копирования, никаких дополнительных аргументов не передается.
- Последний вызывается для реализации операции глубокого копирования, передается один аргумент, memo-словарь.
Если реализации __deepcopy__() необходимо сделать глубокую копию компонента, она должна вызвать функцию copy.deepcopy() с компонентом в качестве первого аргумента и memo-словарем в качестве второго аргумента.
Краткое описание интерфейса.
copy.copy(x) :
Функция copy.copy(x) возвращает мелкую копию x .
copy.deepcopy(x[, memo]) :
Функция copy.deepcopy() возвращает глубокую копию x .
copy.error :
Исключение copy.error возбуждается для специфических ошибок модуля.
Генератор списка с одним и несколькими условиями if и else
Хорошо, теперь давайте посмотрим, как мы можем добавить else после if в генератор списка. Напишем простой генератор списка, который будет сохранять в список e все значения lst , большие 4. Если же какое-то значение меньше 4, вместо него будет сохранена строка less than 4 .
Следующий код выполняет ту же задачу:
А теперь давайте посмотрим, как работают генераторы списков с несколькими if и else .
В приведенном ниже примере мы сохраняем строку Two , если значение кратно 2. А если значение кратно 3, мы сохраняем Three . Во всех остальных случаях мы сохраняем not 2 & 3 .
Как это работает? Чтобы понять это, мы можем разделить всё условие на три части, после каждого else:
'Two' if x%2 == 0 else "Three" if x%3 == 0 else 'not 2 & 3'
Таким образом, если первое условие if истинно, тогда элемент будет принимать значение Two – в противном случае мы вместо сохранения какого-либо значения перейдем ко второму условию if . По такому же принципу работает команда elif . Во втором if-условии в элемент сохранится Three , если утверждение истинно. В противном случае программа проверит следующее условие. Этого условия у нас нет, поэтому элементу будет присвоено значение, идущее сразу после else, — not 2 & 3 .
Мы можем добиться того же результата, написав код следующим образом:
Теперь-то вы видите силу генератора списков? Он выполняет задачу всего в одной строке, в то время как традиционный цикл for состоит из 7.
Сохранение данных книги в виде потока.
Если необходимо сохранить файл в поток, например, при использовании веб-приложения, такого как Flask или Django, то можно просто предоставить tempfile.NamedTemporaryFile() :
Можно указать атрибут template=True , чтобы сохранить книгу как шаблон:
Примечание. Атрибут wb.template по умолчанию имеет значение False , это означает - сохранить как документ.
Внимание. Следующее не удастся:
Генератор списка с вложенным циклом for
Хорошо! Теперь давайте разберем использование вложенного цикла for в генераторе списка.
Чтобы понять, как это работает, давайте рассмотрим приведенный ниже пример. Здесь мы генерируем все возможные комбинации элементов двух списков: [1, 2, 3] и [3, 2, 1] .
Традиционным способом эта задача решалась бы так:
Хорошо, а теперь, как и обещали, давайте сравним обычный цикл for и генератор списков.
Заключение
Итак, мы разобрали на примерах, как в Python получить словарь из списка или двух списков.
Чтобы преобразовать список в словарь, где у всех ключей будут одинаковые значения, можно использовать метод dict.fromkeys() .
Для создания словаря из двух списков стоит воспользоваться функцией zip() .
Генератор словаря позволяет создать новый словарь на основе значений списка.
Надеемся, теперь у вас всё разложилось по полочкам в данном вопросе!
Что же такое генераторы списков в Python?
Итак, начнем с синтаксиса генератора списка. Генератор списка – это одна строка кода, которую вы пишете в квадратных скобках. Он состоит из трех компонентов:
- цикл for
- условие и выражение (condition)
- результат (output)
Пример простого генератора списка
Приведенный ниже фрагмент кода является примером простейшего генератора списка. Здесь мы просто перебираем lst и сохраняем все его элементы в списке a :
Этот код полностью эквивалентен следующему:
Но в первом случае для создания списка а нам даже не нужен метод append . Вместо этого мы используем генератор.
Идем дальше. В приведенном выше генераторе списка можно использовать любое выражение для изменения исходных элементов lst , например:
Создание книги Excel.
Чтобы начать работу с модулем openpyxl , нет необходимости создавать файл электронной таблицы в файловой системе. Нужно просто импортировать класс Workbook и создать его экземпляр. Рабочая книга всегда создается как минимум с одним рабочим листом, его можно получить, используя свойство Workbook.active :
Новый рабочий лист книги Excel.
Новые рабочие листы можно создавать, используя метод Workbook.create_sheet() :
Листам автоматически присваивается имя при создании. Они нумеруются последовательно (Sheet, Sheet1, Sheet2, …). Эти имена можно изменить в любое время с помощью свойства Worksheet.title :
Цвет фона вкладки с этим заголовком по умолчанию белый. Можно изменить этот цвет, указав цветовой код RRGGBB для атрибута листа Worksheet.sheet_properties.tabColor :
Рабочий лист можно получить, используя его имя в качестве ключа экземпляра созданной книги Excel:
Что бы просмотреть имена всех рабочих листов книги, необходимо использовать атрибут Workbook.sheetname . Также можно итерироваться по рабочим листам книги Excel.
Копирование рабочего листа книги Excel.
Для создания копии рабочих листов в одной книге, необходимо воспользоваться методом Workbook.copy_worksheet() :
Примечание. Копируются только ячейки (значения, стили, гиперссылки и комментарии) и определенные атрибуты рабочего листа (размеры, формат и свойства). Все остальные атрибуты книги/листа не копируются, например, изображения или диаграммы.
Поддерживается возможность копирования рабочих листов между книгами. Нельзя скопировать рабочий лист, если рабочая книга открыта в режиме только для чтения или только для записи.
Генератор списка с одиночным и вложенным условием if
В генератор списка также можно добавить if-условие, которое может помочь нам отфильтровать данные. Например, в приведенном ниже коде мы сохраняем в список c все значения lst , большие 4 :
Этот код выполняет то же самое, что и приведенный ниже:
Мы также можем добавить в наш генератор списка вложенное условие if . Например, в приведенном ниже коде мы сохраняем в список d все элементы lst , значения которых больше 4 и кратны 2 :
Этот код эквивалентен данному:
Глубокое (полное) копирование
Глубокая копия создает новую и отдельную копию всего объекта или списка со своим уникальным адресом памяти. Это означает, что любые изменения, внесенные вами в новую копию объекта или списка, не будут отражаться в исходной. Этот процесс происходит следующим образом: сначала создается новый список или объект, а затем рекурсивно копируются все элементы из исходного в новый.
Вроде все так же, как и при поверхностном копировании. Но поведение объектов будет отличаться. Давайте попробуем внести изменения в один из вложенных объектов старого списка:
Результат показывает, что изменения отразились только на старом списке:
Так происходит потому, что при глубоком копировании копируются не ссылки на вложенные объекты, а сами объекты.
В посте использовались материалы статьи «Глубокое и поверхностное копирование в Python» и код из статьи «Python Shallow Copy and Deep Copy».
Генератор списков – это простой для чтения, компактный и элегантный способ создания списка из любого существующего итерируемого объекта. По сути, это более простой способ создания нового списка из значений уже имеющегося списка.
Обычно это одна строка кода, заключенная в квадратные скобки. Вы можете использовать генератор для фильтрации, форматирования, изменения или выполнения других небольших задач с существующими итерируемыми объектами, такими как строки, кортежи, множества, списки и т.д.
Сегодня мы разберем несколько способов создания генератора списков и увидим некоторые их вариации, например:
- Простой генератор списка
- Генераторы списков с одиночными и вложенными условиями if
- Генератор списка с одним и несколькими условиями if и else
- Генератор списков с вложенными циклами for
Помимо этого, мы также рассмотрим следующие концепции:
- Цикл for vs. генератор списка
- Каковы преимущества генератора списка
- Когда использовать, а когда лучше избегать генератора списков
Доступ к ячейке и ее значению.
После того как выбран рабочий лист, можно начинать изменять содержимое ячеек. К ячейкам можно обращаться непосредственно как к ключам рабочего листа, например ws['A4'] . Это вернет ячейку на A4 или создаст ее, если она еще не существует. Значения могут быть присвоены напрямую:
Если объект ячейки присвоить переменной, то этой переменной, также можно присваивать значение:
Существует также метод Worksheet.cell() . Он обеспечивает доступ к ячейкам с непосредственным указанием значений строк и столбцов:
Примечание. При создании рабочего листа в памяти, он не содержит ячеек. Ячейки создаются при первом доступе к ним.
Важно! Из-за такого поведения, простой перебор ячеек в цикле, создаст объекты этих ячеек в памяти, даже если не присваивать им значения.
Не запускайте этот пример, поверьте на слово:
Преимущества генераторов списков
Генератор списков — не только простое, компактное и быстрое, но и надежное решение во многих ситуациях. Его можно использовать в самых разных обстоятельствах. Например, для сопоставления и фильтрации в дополнение к генерации базового списка. Вам не нужно каждый раз изобретать велосипед. Это одна из причин, по которой генераторы списков считаются более «питоничными», чем цикл for .
Удаление рабочего листа книги Excel.
Очевидно, что встает необходимость удалить лист электронной таблицы, который уже существует. Модуль openpyxl дает возможность удалить лист по его имени. Следовательно, сначала необходимо выяснить, какие листы присутствуют в книге, а потом удалить ненужный. За удаление листов книги отвечает метод Workbook.remove() .
Сохранение созданной книги в файл Excel.
Самый простой и безопасный способ сохранить книгу, это использовать метод Workbook.save() объекта Workbook :
Внимание. Эта операция перезапишет существующий файл без предупреждения.
После сохранения, можно открыть полученный файл в Excel и посмотреть данные, выбрав лист с именем NewPage .
Примечание. Расширение имени файла не обязательно должно быть xlsx или xlsm , хотя могут возникнуть проблемы с его открытием непосредственно в другом приложении. Поскольку файлы OOXML в основном представляют собой ZIP-файлы, их также можете открыть с помощью своего любимого менеджера ZIP-архивов.
Добавление данных в ячейки листа списком.
Модуль openpyxl дает возможность супер просто и удобно добавлять данные в конец листа электронной таблицы. Такое удобство обеспечивается методом объекта листа Worksheet.append(iterable) , где аргумент iterable - это любой итерируемый объект (список, кортеж и т.д.). Такое поведение позволяет, без костылей, переносить в электронную таблицу данные из других источников, например CSV файлы, таблицы баз данных, дата-фреймы из Pandas и т.д.
Метод Worksheet.append() добавляет группу значений в последнюю строку, которая не содержит данных.
- Если это список: все значения добавляются по порядку, начиная с первого столбца.
- Если это словарь: значения присваиваются столбцам, обозначенным ключами (цифрами или буквами).
- добавление списка: .append([‘ячейка A1’, ‘ячейка B1’, ‘ячейка C1’])
- добавление словаря:
- вариант 1: .append() , в качестве ключей используются буквы столбцов.
- вариант 2: .append() , в качестве ключей используются цифры столбцов.
Пример добавление данных из списка:
Вот и все, данные добавлены. Просто? Не просто, а супер просто!
Преобразуем список в словарь при помощи генератора словаря
Для преобразования списка Python в словарь также можно использовать генератор словаря.
Генератор словаря похож на генератор списка в том, что оба они создают новое значение соответствующего типа данных.
Что касается синтаксиса, в генераторе словаря используются фигурные скобки <> , а в генераторе списка — квадратные [] .
Давайте преобразуем наш список фруктов в словарь, используя генератор словаря:
Для начала мы объявили список фруктов ( fruits ), где хранятся их названия, которые мы хотим перенести в словарь.
Затем мы использовали генератор словаря, чтобы пройтись по каждому элементу в списке fruits . Для каждого фрукта в нашем списке мы добавили элемент в новый словарь. При этом каждому фрукту мы присвоили значение In stock.
Наконец, мы вывели наш новый словарь в консоль. Можем запустить наш код, и он выведет то же самое, что и в первом примере.
Английский для программистов
Наш телеграм канал с тестами по английскому языку для программистов. Английский это часть карьеры программиста. Поэтому полезно заняться им уже сейчас
Превращаем список в словарь при помощи dict.fromkeys()
Допустим, у нас есть список фруктов, которые мы хотим превратить в словарь. Значение, присвоенное каждому фрукту, должно быть In stock (т.е. в наличии):
Создадим этот словарь с помощью dict.fromkeys() . Этот метод принимает список ключей, которые вы хотите превратить в словарь. При желании можно указать значение, которое должно быть присвоено всем ключам.
Значение можно указать только одно. То есть нельзя прописать, что один ключ должен иметь одно значение, а другой ключ — другое.
Давайте превратим наш список фруктов в словарь:
Наш код возвращает объекты из этого списка в виде словаря:
Сначала мы объявляем переменную под именем fruits . В ней хранятся имена ключей, которые мы хотим использовать в нашем словаре.
Затем мы используем метод dict.fromkeys() для создания словаря с ключами, которые мы сохранили в списке fruits . Этот метод присваивает каждому ключу значение In stock .
Наконец, мы выводим получившийся словарь в консоль.
Если бы мы не указали в нашем коде значение In stock , значением по умолчанию для ключей в нашем словаре было бы None .
Читайте также: