Python list tuple разница

Оптимизации, используемые в Python: список и кортеж

В Python, есть два похожих типа — список (list) и кортеж (tuple). Самая известная разница между ними состоит в том, что кортежи неизменяемы.

Вы не можете изменить объекты в tuple:

>>> a = (1,2,3) >>> a[0] = 10 Traceback (most recent call last): File "", line 1, in TypeError: 'tuple' object does not support item assignment 

Но вы можете модифицировать изменяемые объекты внутри кортежа:

>>> b = (1,[1,2,3],3) >>> b[1] [1, 2, 3] >>> b[1].append(4) >>> b (1, [1, 2, 3, 4], 3) 

Внутри CPython (стандартного интерпретатора), список и кортеж реализованы как лист из указателей (ссылок) на Python объекты, т.е. физически они не хранят объекты рядом с друг другом. Когда вы удаляете объект из списка происходит удаление ссылки на этот объект. Если на объект ещё кто-то ссылается, то он продолжит находиться в памяти.

Кортежи

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

Вы можете не замечать, но вы используете кортежи когда:

  • работаете с аргументами или параметрами (они хранятся как кортежи)
  • возвращаете две или более переменных из функции
  • итерируете ключи-значения в словаре
  • используете форматирование строк
>>> import gc >>> def type_stats(type_obj): . count = 0 . for obj in gc.get_objects(): . if type(obj) == type_obj: . count += 1 . return count . >>> type_stats(tuple) 3136 >>> type_stats(list) 659 >>> import pandas >>> type_stats(tuple) 6953 >>> type_stats(list) 2455 

Пустые списки vs пустые кортежи

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

>>> a = () >>> b = () >>> a is b True >>> id(a) 4409020488 >>> id(b) 4409020488 >>> # В CPython, функция id возвращает адрес в памяти. 

Но это не работает со списками, ведь они могут быть изменены:

>>> a = [] >>> b = [] >>> a is b False >>> id(a) 4465566920 >>> id(b) 4465370632 

Оптимизация выделения памяти для кортежей

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

Этот список разделен на 20 групп, где каждая группа представляет из себя список кортежей размера n, где n от 0 до 20. Каждая группа может хранить до 2 000 свободных кортежей. Первая группа хранит только один элемент и представляет из себя список из одного пустого кортежа.

>>> a = (1,2,3) >>> id(a) 4427578104 >>> del a >>> b = (1,2,4) >>> id(b) 4427578104 

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

Оптимизация выделения памяти для списков

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

>>> a = [] >>> id(a) 4465566792 >>> del a >>> b = [] >>> id(b) 4465566792 

Изменение размера списка

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

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

Паттерн роста размера списка выглядит примерно так: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88,…

Для примера, если вы хотите добавить новый элемент в список с 8 элементами, то свободных ячеек в нём уже не будет и Python сразу расширит его размер до 16 ячеек, где 9 из них будут заняты и видны пользователю.

Формула выбора размера написанная на Python:

>>> def get_new_size(n_items): . new_size = n_items + (n_items // 2 ** 3) . if n_items < 9: . new_size += 3 . else: . new_size += 6 . . return new_size . >>> get_new_size(9) 16 

Скорость

Если сравнивать эти два типа по скорости, то в среднем по больнице, кортежи слегка быстрее списков. У Raymond Hettinger есть отличное объяснение разницы в скорости на stackoverflow.

P.S.: Я являюсь автором этой статьи, можете задавать любые вопросы.

Источник

Python List vs. Tuple

difference between list and tuple in python

difference between list and tuple in python

В этой статье будет рассмотрена разница между списком и кортежем (List vs. Tuple).

List и Tuple в Python — это классы структур данных Python. Список является динамическим, тогда как кортеж имеет статические характеристики. Это означает, что списки могут быть изменены, тогда как кортежи не могут быть изменены, кортеж быстрее списка из-за статичности по своей природе. Списки обозначаются квадратными скобками, а кортежи обозначаются скобками.

Важные различия между List и Tuple в Python

List (список) Tuple (Кортеж)
1 Списки изменяемы Кортежи неизменны
2 Последствия итераций отнимают много времени Последствия итераций сравнительно быстрее
3 Список лучше подходит для выполнения операций, таких как вставка и удаление. Тип данных Tuple подходит для доступа к элементам
4 Списки потребляют больше памяти Кортеж потребляет меньше памяти по сравнению со списком
5 Списки имеют несколько встроенных методов. Tuple не имеет большого количества встроенных методов.
6 Более вероятны непредвиденные изменения и ошибки В кортеже это трудно осуществить.

Список против кортежа

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

# Creating a List with # the use of Numbers # code to test that tuples are mutable List = [1, 2, 4, 4, 3, 3, 3, 6, 5] print("Original list ", List) List[3] = 77 print("Example to show mutablity ", List)

Результат выполнения кода:

Исходный список [1, 2, 4, 4, 3, 3, 3, 6, 5] Пример для демонстрации изменчивости [1, 2, 4, 77, 3, 3, 3, 6, 5]

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

tuple1 = (0, 1, 2, 3) tuple1[0] = 4 print(tuple1)

Результат выполнения кода:

Traceback (most recent call last): File "tuple_example.py", line 3, in tuple1[0]=4 TypeError: 'tuple' object does not support item assignment

Проверка эффективности работы кортежей с памятью

Поскольку кортежи хранятся в одном блоке памяти, им не требуется дополнительное пространство для новых объектов, в то время как списки размещаются в двух блоках: первый фиксированный со всей информацией об объектах Python, а второй блок переменного размера для данных.

import sys a_list = [] a_tuple = () a_list = ["Lemons", "And", "Apples"] a_tuple = ("Lemons", "And", "Apples") print(sys.getsizeof(a_list)) print(sys.getsizeof(a_tuple))

Результат выполнения кода:

Проверка скорости итераций в Tuple по сравнению с List

import sys, platform import time l=list(range(100000001)) t=tuple(range(100000001)) start = time.time_ns() for i in range(len(t)): a = t[i] end = time.time_ns() print("Total lookup time for Tuple: ", end - start) start = time.time_ns() for i in range(len(l)): a = l[i] end = time.time_ns() print("Total lookup time for LIST: ", end - start)

Результат выполнения кода:

Общее время поиска для Tuple: 7038208700 Общее время поиска для LIST: 19646516700

Источник

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

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

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

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

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

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

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

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

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

  • Отличие 1: дубликаты.
    Говоря проще, List и Tuple в Python как двойняшки разного пола, а тип данных Set для них как двоюродный брат. В отличие от списков или кортежей, множество не содержит дубликатов. Другими словами, элементы множества всегда уникальны. Получается, что множество удобно удаляет дубликаты, словно создано именно для этого.
  • Отличие 2: упорядоченность.
    Наверняка вы слышали утверждение “множества и словари в Python не упорядочены”, но на сегодняшний день — это лишь половина правды в зависимости от того, какой версией Python вы пользуетесь. До Python версии 3.6 словари и множества действительно не сохраняли порядок элементов, но начиная с Python 3.7, dictionary и set официально упорядочены по времени добавления элементов. А вот list и tuple — это всегда упорядоченные последовательности объектов.
# Пример тогда ещё неупорядоченного множества в Python версии 3.5 fruit_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.

Источник

Читайте также:  Php numeric value test
Оцените статью