Главная страница
Навигация по странице:

  • 14.4. Удаление из списка

  • 14.5. Сортировка списков

  • 14.6. Полезные советы по работе со списками

  • Этап 1: Python создает список

  • Этап 3: Назначается переменная nums_sorted [ , , , ]Id:4f5aType:List nums_sortedРис. 14.3.

  • СОВЕТ Когда стоит использовать множество вместо списка Вспомните, что мно- жества оптимизированы для проверки принадлежности и удаления дубли- 128

  • Как устроен Python. Как устроен Python. Харрисон. Харрисон Мэтт


    Скачать 5.41 Mb.
    НазваниеХаррисон Мэтт
    АнкорКак устроен Python
    Дата05.02.2022
    Размер5.41 Mb.
    Формат файлаpdf
    Имя файлаКак устроен Python. Харрисон.pdf
    ТипДокументы
    #352210
    страница10 из 21
    1   ...   6   7   8   9   10   11   12   13   ...   21
    14.2. Индексы
    Список — один из типов последовательностей в языке Python. В по- следовательностях хранятся упорядоченные наборы объектов. Чтобы

    14.3. Вставка в список
    115
    эффективно работать с последовательностями, необходимо понимать, что такое индекс. С каждым элементом списка связан индекс, описы- вающий его местоположение в списке. Например, при изготовлении картофельных чипсов используется картофель, масло и соль, которые обычно перечисляются именно в таком порядке. Картофель находится на первом месте списка, масло на втором, а соль на третьем.
    Во многих языках программирования первому элементу последователь- ности присваивается индекс 0, второму — индекс 1, третьему — индекс 2, и т. д. Нумерация индексов начинается с нуля.
    Для обращения к элементу списка указывается индекс этого элемента, заключенный в квадратные скобки:
    >>> names[0]
    'Matt'
    >>> names[1]
    'Fred'
    14.3. Вставка в список
    Чтобы вставить элемент в позицию с определенным индексом, исполь- зуйте метод
    .insert
    . При вызове
    .insert все элементы, следующие за этим индексом, сдвигаются вправо:
    >>> names.insert(0, 'George')
    >>> print(names)
    ['George', 'Matt', 'Fred']
    Для замены элемента с заданным индексом применяется синтаксис с квадратными скобками:
    >>> names[1] = 'Henry'
    >>> print(names)
    ['George', 'Henry', 'Fred']
    Чтобы присоединить элементы в конец списка, воспользуйтесь методом
    .append
    :
    >>> names.append('Paul')
    >>> print(names)
    ['George', 'Henry', 'Fred', 'Paul']

    116
    Глава 14. Контейнеры: списки, кортежи и множества
    ПРИМЕЧАНИЕ
    В Python списки в действительности реализуются в виде массива указателей.
    Такая реализация обеспечивает быстрый произвольный доступ к элемен- там по индексам. Кроме того, операции присоединения и удаления в конце списка выполняются быстро (O(1)), тогда как операции вставки и удаления в середине списка выполняются медленнее (O(n)). Если окажется, что вам часто приходится вставлять и извлекать элементы в начале списка, лучше использовать структуру данных collections.deque
    14.4. Удаление из списка
    Для удаления элементов из списка используется метод
    .remove
    :
    >>> names.remove('Paul')
    >>> print(names)
    ['George', 'Henry', 'Fred']
    Также возможно удаление по индексу с использованием синтаксиса с квадратными скобками:
    >>> del names[1]
    >>> print(names)
    ['George', 'Fred']
    14.5. Сортировка списков
    Одна из самых распространенных операций со списками — сортировка.
    Метод
    .sort упорядочивает значения в списке, при этом сортировка осуществляется «на месте». Метод не возвращает новую отсортиро- ванную копию списка, а обновляет список с измененным порядком элементов:
    >>> names.sort()
    >>> print(names)
    ['Fred', 'George']
    Если предыдущий порядок элементов важен, скопируйте список перед сортировкой. Впрочем, для сортировки последовательностей также

    14.6. Полезные советы по работе со списками
    117
    можно воспользоваться более общим решением с функцией sorted
    Функция sorted работает с любой последовательностью и возвращает новый список с упорядоченными элементами:
    >>> old = [5, 3, -2, 1]
    >>> nums_sorted = sorted(old)
    >>> print(nums_sorted)
    [-2, 1, 3, 5]
    >>> print(old)
    [5, 3, -2, 1]
    Будьте внимательны с тем, что вы сортируете. Python требует, чтобы вы явно выражали свои намерения. В Python 3 при попытке отсортировать список с разнотипными элементами может произойти ошибка:
    >>> things = [2, 'abc', 'Zebra', '1']
    >>> things.sort()
    Traceback (most recent call last):
    TypeError: unorderable types: str() < int()
    Как метод
    .sort
    , так и функция sorted позволяют управлять сорти- ровкой, для чего в параметре key передается произвольная функция сортировки. Параметр key может содержать функцию (а также класс или метод), которая получает один элемент и возвращает нечто при- годное для сравнения.
    В следующем примере, где в параметре key передается str
    , все элементы списка сортируются по правилам сортировки строк:
    >>> things.sort(key=str)
    >>> print(things)
    ['1', 2, 'Zebra', 'abc']
    14.6. Полезные советы по работе
    со списками
    Обычно списки также поддерживают другие методы. Попробуйте от- крыть интерпретатор Python и ввести несколько примеров. Не забывайте о своих друзьях dir и help

    118
    Глава 14. Контейнеры: списки, кортежи и множества
    СОВЕТ
    Встроенная функция range строит целочисленные последовательности.
    Следующий фрагмент создает последовательность из чисел от 0 до 4:
    >>> nums = range(5)
    >>> nums range(5)
    Python 3 не любит лишней работы. Функция range не материализует список, а предоставляет итератор, который будет возвращать эти числа при переборе.
    Передав результат list
    , вы сможете увидеть сгенерированные числа:
    >>> list(nums)
    [0, 1, 2, 3, 4]
    Обратите внимание: сгенерированная последовательность не включает чис- ло 5. Многие функции Python, использующие конечные индексы, означают
    «до, но не включая» (другой пример такого рода — срезы — будет представлен позднее).
    Если последовательность должна начинаться с ненулевого числа, функции range можно передать два параметра. В этом случае первый параметр опре- деляет начало последовательности (включительно), а второй — конец (не включая):
    # Числа от 2 до 5
    >>> nums2 = range(2, 6)
    >>> nums2
    range(2, 6)
    У функции range также имеется необязательный третий параметр — при-
    ращение. Если приращение равно 1 (по умолчанию), следующее число в по- следовательности, возвращаемой range
    , будет на 1 больше предыдущего.
    С приращением 2 будет возвращаться каждое второе число. В следующем примере возвращаются только четные числа, меньшие 11:
    >>> even = range(0, 11, 2)
    >>> even range(0, 11, 2)
    >>> list(even)
    [0, 2, 4, 6, 8, 10]

    14.6. Полезные советы по работе со списками
    119
    Сортировка списков names = ['George','Fred']
    Код
    Что делает компьютер
    Переменные Объекты
    Переменные Объекты
    [ , ]
    Id:4f3b
    Type:List names
    "George"
    Id:4f3f
    Type:String
    "Fred"
    Id:4f4a
    Type:String
    Этап 1: Python создает список
    names.sort()
    [ , ]
    Id:4f3b
    Type:List names
    "George"
    Id:4f3f
    Type:String
    "Fred"
    Id:4f4a
    Type:String
    Этап 2: Python сортирует список «на месте»
    Не в озвращае т спис ок
    !
    Рис. 14.1. Сортировка списка методом .sort. Помните, что список сортируется
    «на месте». В результате вызова метода .sort список изменяется, а сам метод возвращает None

    120
    Глава 14. Контейнеры: списки, кортежи и множества
    Сортировка списков функцией sorted old = [5, 3, -2, 1]
    Код
    Что делает компьютер
    Переменные Объекты
    Переменные
    Объекты
    [ , , , ]
    Id:4f3b
    Type:List old
    5
    Int nums_sorted = sorted(old)
    3
    Int
    -2
    Int
    1
    Int
    Этап 1: Python создает список
    old = [5, 3, -2, 1]
    [ , , , ]
    Id:4f3b
    Type:List old
    5
    Int nums_sorted = sorted(old)
    3
    Int
    -2
    Int
    1
    Int
    Этап 2: Функция sorted создает новый список
    [ , , , ]
    Id:4f5a
    Type:List
    Рис. 14.2. Сортировка списка функцией sorted. Обратите внимание: список не изменяется, а при вызове возвращается новый список. Кроме того, Python повторно использует элементы списка, не создавая новых элементов

    14.6. Полезные советы по работе со списками
    121
    old = [5, 3, -2, 1]
    Переменные Объекты
    [ , , , ]
    Id:4f3b
    Type:List old
    5
    Int nums_sorted = sorted(old)
    3
    Int
    -2
    Int
    1
    Int
    Этап 3: Назначается переменная nums_sorted
    [ , , , ]
    Id:4f5a
    Type:List nums_sorted
    Рис. 14.3. На последнем этапе в результате операции присваивания переменная указывает на новый список. Обратите внимание: функция sorted работает с любыми последовательностями, не только со списками
    ПРИМЕЧАНИЕ
    Конструкция «до, но не включая» более формально называется полуот-
    крытым интервалом. Обычно полуоткрытые интервалы используются при определении последовательностей натуральных чисел. Они обладают рядом удобных свойств:
    • Длина серии последовательных чисел равна разности между концом и началом интервала.
    • Сращивание двух подпоследовательностей обходится без перекрытия.
    В Python идиома полуоткрытого интервала применяется достаточно часто.
    Пример:

    122
    Глава 14. Контейнеры: списки, кортежи и множества
    >>> a = range(0, 5)
    >>> b = range(5, 10)
    >>> both = list(a) + list(b)
    >>> len(both) # 10 - 0 10
    >>> both
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    Если вы часто работаете с числовыми последовательностями, вам стоит по- ступать так же — особенно при определении API.
    Знаменитый теоретик в области программирования Эдгар Дейкстра (Edsger
    Dijkstra) размышлял об индексировании с 0 и о том, почему этот вариант правилен
    1
    . Он завершает свои рассуждения так:
    «Многие языки программирования проектировались без должного внимания к этой подробности».
    К счастью, Python к числу таких языков не относится.
    14.7. Кортежи
    Кортежи (tuples) представляют собой неизменяемые последовательно- сти. Их можно рассматривать как упорядоченные записи данных. После того как кортеж будет создан, изменить его не удастся. Чтобы создать кортеж с использованием синтаксиса литерала, заключите компоненты в круглые скобки и разделите их запятыми. Также имеется класс tuple
    , который может использоваться для построения нового кортежа из су- ществующей последовательности:
    >>> row = ('George', 'Guitar')
    >>> row
    ('George', 'Guitar')
    >>> row2 = ('Paul', 'Bass')
    >>> row2
    ('Paul', 'Bass')
    1
    https://www.cs.utexas.edu/users/EWD/transcriptions/EWD08xx/EWD831.html

    14.7. Кортежи
    123
    Можно создать кортеж с нулем или с одним элементом. На практике кортежи используются для хранения записей данных, поэтому такой вариант встречается нечасто. Есть два способа создания пустых корте- жей — функция tuple и синтаксис литералов:
    >>> empty = tuple()
    >>> empty
    ()
    >>> empty = ()
    >>> empty
    ()
    Кортеж с одним элементом можно создать тремя способами:
    >>> one = tuple([1])
    >>> one
    (1,)
    >>> one = (1,)
    >>> one
    (1,)
    >>> one = 1,
    >>> one
    (1,)
    ПРИМЕЧАНИЕ
    Круглые скобки используются в Python для обозначения вызовов функций или методов. Кроме того, они используются для определения приоритета операторов и еще могут использоваться при создании кортежей. Такое обилие применений может привести к недоразумениям. Запомните простое прави- ло: если в круглые скобки заключен один элемент, то Python рассматривает круглые скобки как обычные (для определения приоритета операторов) — например, как в записи (2
    +
    3)
    *
    8. Если же в скобки заключено несколько элементов, разделенных запятыми, Python рассматривает их как кортеж:
    >>> d = (3)
    >>> type(d)

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

    124
    Глава 14. Контейнеры: списки, кортежи и множества из одного элемента, следует поставить после элемента запятую (
    ,
    ) или же использовать класс tuple со списком, состоящим из одного элемента:
    >>> e = (3,)
    >>> type(e)

    Создать кортеж с несколькими элементами можно тремя способами.
    Обычно последний считается наиболее соответствующим стилю Python.
    Благодаря наличию круглых скобок проще увидеть, что перед вами кортеж:
    >>> p = tuple(['Steph', 'Curry', 'Guard'])
    >>> p
    ('Steph', 'Curry', 'Guard')
    >>> p = 'Steph', 'Curry', 'Guard'
    >>> p
    ('Steph', 'Curry', 'Guard')
    >>> p = ('Steph', 'Curry', 'Guard')
    >>> p
    ('Steph', 'Curry', 'Guard')
    Так как кортежи являются неизменяемыми, присоединение к ним новых элементов невозможно:
    >>> p.append('Golden State')
    Traceback (most recent call last):
    File "", line 1, in
    AttributeError: 'tuple' object has no attribute
    'append'
    ПРИМЕЧАНИЕ
    Почему кортежи и списки существуют по отдельности? Почему бы просто не использовать списки, которые на первый взгляд являются надмножеством кортежей?
    Главное различие между объектами заключается в изменяемости. Так как кортежи неизменяемы, они могут служить ключами в словарях. Кортежи часто используются для представления записей данных — например, строк

    14.8. Множества
    125
    запросов баз данных, которые могут содержать разнородные типы объектов.
    Например, в кортеже могут храниться имя, адрес и возраст:
    >>> person = ('Matt', '123 North 456 East', 24)
    Кортежи используются для возвращения нескольких элементов из функций.
    Кроме того, они подсказывают разработчику, что этот тип не предназначен для изменения.
    Наконец, кортежи используют меньше памяти, чем списки. Если вы работа- ете с последовательностями, которые не должны изменяться, возможно, вам стоит воспользоваться кортежами ради экономии памяти.
    14.8. Множества
    Еще одну разновидность контейнеров в Python составляют множества
    (set). Множество представляет собой неупорядоченную совокупность объектов, в которой не может быть дубликатов. Как и кортеж, множество можно создать на базе списка или других последовательностей, элементы которых можно перебирать. Однако, в отличие от списков и кортежей, для множеств неважен порядок элементов. Множества часто используют- ся для двух целей: для удаления дубликатов и для проверки принадлеж- ности. Так как механизм поиска основан на оптимизированной функции хеширования, реализованной для словарей, операция поиска занимает очень мало времени даже для очень больших множеств.
    ПРИМЕЧАНИЕ
    Так как множества должны вычислять хеш-код для каждого элемента, в них могут храниться только хешируемые элементы. Хеш-код представляет со- бой квазиуникальное число, сгенерированное для заданного объекта. Если объект является хешируемым, для него всегда генерируется одно и то же число.
    В языке Python изменяемые элементы не являются хешируемыми. Это озна- чает, что хешировать список или словарь невозможно. Для хеширования поль- зовательских классов необходимо реализовать методы
    __hash__
    и
    __eq__
    Множество можно определить передачей последовательности классу set
    (еще один класс преобразования, который выглядит как функция):

    126
    Глава 14. Контейнеры: списки, кортежи и множества
    >>> digits = [0, 1, 1, 2, 3, 4, 5, 6,
    ... 7, 8, 9]
    >>> digit_set = set(digits) # Удаление лишней 1
    Множества также могут создаваться в синтаксисе литералов с
    {
    }
    :
    >>> digit_set = {0, 1, 1, 2, 3, 4, 5, 6,
    ... 7, 8, 9}
    Как упоминалось выше, множество отлично подходит для удале- ния дубликатов. При создании множества на базе последовательности все дубликаты удаляются. Так, из digit_set был удален лишний эле- мент 1:
    >>> digit_set
    {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    Для проверки принадлежности используется операция in
    :
    >>> 9 in digit_set
    True
    >>> 42 in digit_set
    False
    ПРИМЕЧАНИЕ
    В Python существует особый протокол принадлежности. Если класс (мно- жество, список или класс, определяемый пользователем) реализует метод
    __contains__
    (или протокол перебора), он может использоваться для про- верки принадлежности. Вследствие особенностей реализации множеств проверка принадлежности для них может выполняться намного быстрее, чем проверки по списку.
    В следующем примере создается множество с именем odd
    . Оно будет использоваться в дальнейших примерах:
    >>> odd = {1, 3, 5, 7, 9}
    Множества Python поддерживают классические операции теории мно- жеств, такие как объединение (
    |
    ), пересечение (
    &
    ), вычитание (
    -
    ) и ис- ключающее ИЛИ (
    ^
    ).

    14.8. Множества
    127
    Оператор вычитания (
    -
    ) удаляет элементы, входящие в одно множество, из другого множества:
    >>> odd = {1, 3, 5, 7, 9}
    # Вычитание
    >>> even = digit_set - odd
    >>> even
    {0, 8, 2, 4, 6}
    Обратите внимание на порядок элементов результата: на первый взгляд он кажется произвольным. Если для вас важен порядок элементов, вместо множества лучше использовать другой тип данных.
    Операция пересечения (
    &
    ) возвращает элементы, присутствующие в обо- их множествах:
    >>> prime = set([2, 3, 5, 7])
    # В обоих множествах
    >>> prime_even = prime & even
    >>> prime_even
    {2}
    Операция объединения (
    |
    ) возвращает множество, состоящее из всех элементов обоих множеств (с исключением дубликатов):
    >>> numbers = odd | even
    >>> print(numbers)
    {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    Операция исключающего ИЛИ (
    ^
    ) возвращает множество с элементами, присутствующими только в одном из двух множеств:
    >>> first_five = set([0, 1, 2, 3, 4])
    >>> two_to_six = set([2, 3, 4, 5, 6])
    >>> in_one = first_five ^ two_to_six
    >>> print(in_one)
    {0, 1, 5, 6}
    СОВЕТ
    Когда стоит использовать множество вместо списка? Вспомните, что мно- жества оптимизированы для проверки принадлежности и удаления дубли-

    128
    Глава 14. Контейнеры: списки, кортежи и множества катов. Если вы выполняете операции объединения или вычитания списков, возможно, вам стоит вместо списков использовать множества.
    Множества также намного эффективнее работают при проверке принадлеж- ности. Оператор in для множеств работает быстрее, чем для списков. Тем не менее за эту скорость приходится расплачиваться: в отличие от списков и кортежей, множества не поддерживают конкретный порядок хранения элементов. Если для вас важен порядок элементов, используйте структуру данных, в которой он сохраняется.
    14.9. Итоги
    В этой главе описаны некоторые встроенные типы-контейнеры. Сначала были рассмотрены списки — изменяемые упорядоченные последова- тельности. Помните, что методы списков не возвращают новый список, а обычно изменяют список «на месте». Списки поддерживают вставку произвольных элементов, но обычно в списке хранятся однотипные элементы.
    Затем были рассмотрены кортежи. Кортежи тоже упорядочены, как и списки, но в отличие от списков кортежи не поддерживают изменение
    «на месте». На практике они обычно используются для представления записей данных — например, строк, прочитанных из базы данных. В кор- тежах, представляющих записи данных, могут храниться разные типы объектов.
    В завершение главы были представлены множества. Множества явля- ются изменяемыми, но они не упорядочены. Они используются для удаления дубликатов и проверки принадлежности. Из-за используемого механизма хеширования операции с множествами выполняются быстро и эффективно. Для этого элементы множества должны быть хешируе- мыми.
    1   ...   6   7   8   9   10   11   12   13   ...   21


    написать администратору сайта