ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 05.12.2023
Просмотров: 837
Скачиваний: 3
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
СОДЕРЖАНИЕ
")) input()
Результат выполнения:
Метод subn()
аналогичен методу sub()
, но возвращает не строку, а кортеж из двух элемен- тов: измененной строки и количества произведенных замен. Метод имеет следующий фор- мат: subn(<Новый фрагмент или ссылка на функцию>, <Строка для замены>
[, <Максимальное количество замен>])
Заменим все числа в строке на
0
:
>>> p = re.compile(r"[0-9]+")
>>> p.subn("0", "2008, 2009, 2010, 2011")
('0, 0, 0, 0', 4)
Вместо метода subn()
можно воспользоваться функцией subn()
. Формат функции: re.subn(<Шаблон>, <Новый фрагмент или ссылка на функцию>,
<Строка для замены>[, <Максимальное количество замен>
[, flags=0]])
Глава 7. Регулярные выражения
139
В качестве параметра
<Шаблон>
можно указать строку с регулярным выражением или ском- пилированное регулярное выражение:
>>> p = r"200[79]"
>>> re.subn(p, "2001", "2007, 2008, 2009, 2010")
('2001, 2008, 2001, 2010', 2)
Для выполнения замен также можно использовать метод expand()
, поддерживаемый объек- том
Match
. Формат метода: expand(<Шаблон>)
Внутри указанного шаблона можно использовать обратные ссылки:
\номер группы
,
\g<номер группы>
и
\g<название группы>
:
>>> p = re.compile(r"<(?P
>>> m = p.search("
")
>>> m.expand(r"<\2><\1>") # \номер '
'
>>> m.expand(r"<\g<2>><\g<1>>") # \g<номер>
'
'
>>> m.expand(r"<\g
'
'
7.5. Прочие функции и методы
Метод split()
разбивает строку по шаблону и возвращает список подстрок. Его формат: split(<Исходная строка>[, <Лимит>])
Если во втором параметре задано число, то в списке окажется указанное количество под- строк. Если подстрок больше указанного количества, то список будет содержать еще один элемент — с остатком строки:
>>> import re
>>> p = re.compile(r"[\s,.]+")
>>> p.split("word1, word2\nword3\r\nword4.word5")
['word1', 'word2', 'word3', 'word4', 'word5']
>>> p.split("word1, word2\nword3\r\nword4.word5", 2)
['word1', 'word2', 'word3\r\nword4.word5']
Если разделитель в строке не найден, список будет состоять только из одного элемента, содержащего исходную строку:
>>> p = re.compile(r"[0-9]+")
>>> p.split("word, word\nword")
['word, word\nword']
Вместо метода split()
можно воспользоваться функцией split()
. Формат функции: re.split(<Шаблон>, <Исходная строка>[, <Лимит>[, flags=0]])
В качестве параметра
<Шаблон>
можно указать строку с регулярным выражением или ском- пилированное регулярное выражение:
>>> p = re.compile(r"[\s,.]+")
>>> re.split(p, "word1, word2\nword3")
['word1', 'word2', 'word3']
140
Часть I. Основы языка Python
>>> re.split(r"[\s,.]+", "word1, word2\nword3")
['word1', 'word2', 'word3']
Функция escape(<Строка>)
экранирует все специальные символы в строке, после чего ее можно безопасно использовать внутри регулярного выражения:
>>> print(re.escape(r"[]().*"))
\[\]\(\)\.\*
Функция purge()
выполняет очистку кэша, в котором хранятся промежуточные данные, используемые в процессе выполнения регулярных выражений. Ее рекомендуется вызывать после обработки большого количества регулярных выражений. Результата эта функция не возвращает:
>>> re.purge()
ГЛ А В А
8
Списки, кортежи, множества и диапазоны
Списки, кортежи, множества и диапазоны — это нумерованные наборы объектов. Каж- дый элемент набора содержит лишь ссылку на объект — по этой причине они могут содер- жать объекты произвольного типа данных и иметь неограниченную степень вложенности.
Позиция элемента в наборе задается индексом. Обратите внимание на то, что нумерация элементов начинается с
0
, а не с
1
Списки и кортежи являются просто упорядоченными последовательностями элементов. Как и все последовательности, они поддерживают обращение к элементу по индексу, получение среза, конкатенацию (оператор
+
), повторение (оператор
*
), проверку на вхождение (оператор in
) и невхождение (оператор not in
).
Списки относятся к изменяемым типам данных. Это означает, что мы можем не только получить элемент по индексу, но и изменить его:
>>> arr = [1, 2, 3] # Создаем список
>>> arr[0] # Получаем элемент по индексу
1
>>> arr[0] = 50 # Изменяем элемент по индексу
>>> arr
[50, 2, 3]
Кортежи относятся к неизменяемым типам данных. Иными словами, можно получить элемент по индексу, но изменить его нельзя:
>>> t = (1, 2, 3) # Создаем кортеж
>>> t[0] # Получаем элемент по индексу
1
>>> t[0] = 50 # Изменить элемент по индексу нельзя!
Traceback (most recent call last):
File "
", line 1, in
TypeError: 'tuple' object does not support item assignment
Множества могут быть как изменяемыми, так и неизменяемыми. Их основное отличие от только что рассмотренных типов данных — хранение лишь уникальных значений
(неуникальные значения автоматически отбрасываются):
>>> set([0, 1, 1, 2, 3, 3, 4])
{0, 1, 2, 3, 4}
142
Часть I. Основы языка Python
Что касается диапазонов, то они представляют собой наборы чисел, сформированные на основе заданных начального, конечного значений и величины шага между числами. Их важнейшее преимущество перед всеми остальными наборами объектов — небольшой объем занимаемой оперативной памяти:
>>> r = range(0, 101, 10)
>>> for i in r: print(i, end = " ")
0 10 20 30 40 50 60 70 80 90 100
Рассмотрим все упомянутые типы данных более подробно.
8.1. Создание списка
Создать список можно следующими способами:
с помощью функции list([<Последовательность>])
. Функция позволяет преобразовать любую последовательность в список. Если параметр не указан, создается пустой список:
>>> list() # Создаем пустой список
[]
>>> list("String") # Преобразуем строку в список
['S', 't', 'r', 'i', 'n', 'g']
>>> list((1, 2, 3, 4, 5)) # Преобразуем кортеж в список
[1, 2, 3, 4, 5]
указав все элементы списка внутри квадратных скобок:
>>> arr = [1, "str", 3, "4"]
>>> arr
[1, 'str', 3, '4']
заполнив список поэлементно с помощью метода append()
:
>>> arr = [] # Создаем пустой список
>>> arr.append(1) # Добавляем элемент1 (индекс 0)
>>> arr.append("str") # Добавляем элемент2 (индекс 1)
>>> arr
[1, 'str']
В некоторых языках программирования (например, в PHP) можно добавить элемент, указав пустые квадратные скобки или индекс больше последнего индекса. В языке Python все эти способы приведут к ошибке:
>>> arr = []
>>> arr[] = 10
SyntaxError: invalid syntax
>>> arr[0] = 10
Traceback (most recent call last):
File "
", line 1, in
IndexError: list assignment index out of range
При создании списка в переменной сохраняется ссылка на объект, а не сам объект. Это обя- зательно следует учитывать при групповом присваивании. Групповое присваивание можно использовать для чисел и строк, но для списков этого делать нельзя. Рассмотрим пример:
Глава 8. Списки, кортежи, множества и диапазоны
143
>>> x = y = [1, 2] # Якобы создали два объекта
>>> x, y
([1, 2], [1, 2])
В этом примере мы создали список из двух элементов и присвоили значение переменным x
и y
. Теперь попробуем изменить значение в переменной y
:
>>> y[1] = 100 # Изменяем второй элемент
>>> x, y # Изменилось значение сразу в двух переменных
([1, 100], [1, 100])
Как видно из примера, изменение значения в переменной y
привело также к изменению значения в переменной x
. Таким образом, обе переменные ссылаются на один и тот же объ- ект, а не на два разных объекта. Чтобы получить два объекта, необходимо производить раз- дельное присваивание:
>>> x, y = [1, 2], [1, 2]
>>> y[1] = 100 # Изменяем второй элемент
>>> x, y
([1, 2], [1, 100])
Точно такая же ситуация возникает при использовании оператора повторения
*
. Например, в следующей инструкции производится попытка создания двух вложенных списков с по- мощью оператора
*
:
>>> arr = [ [] ] * 2 # Якобы создали два вложенных списка
>>> arr
[[], []]
>>> arr[0].append(5) # Добавляем элемент
>>> arr # Изменились два элемента
[[5], [5]]
Создавать вложенные списки следует с помощью метода append()
внутри цикла:
>>> arr = []
>>> for i in range(2): arr.append([])
>>> arr
[[], []]
>>> arr[0].append(5); arr
[[5], []]
Можно также воспользоваться генераторами списков:
>>> arr = [ [] for i in range(2) ]
>>> arr
[[], []]
>>> arr[0].append(5); arr
[[5], []]
Проверить, ссылаются ли две переменные на один и тот же объект, позволяет оператор is
Если переменные ссылаются на один и тот же объект, оператор is возвращает значение
True
:
>>> x = y = [1, 2] # Неправильно
>>> x is y # Переменные содержат ссылку на один и тот же список
True
144
Часть I. Основы языка Python
>>> x, y = [1, 2], [1, 2] # Правильно
>>> x is y # Это разные объекты
False
Но что же делать, если необходимо создать копию списка? Первый способ заключается в применении операции извлечения среза, второй — в использовании функции list()
, а третий — в вызове метода copy()
:
>>> x = [1, 2, 3, 4, 5] # Создали список
>>> # Создаем копию списка
>>> y = list(x) # или с помощью среза: y = x[:]
>>> # или вызовом метода copy(): y = x.copy()
>>> y
[1, 2, 3, 4, 5]
>>> x is y # Оператор показывает, что это разные объекты
False
>>> y[1] = 100 # Изменяем второй элемент
>>> x, y # Изменился только список в переменной y
([1, 2, 3, 4, 5], [1, 100, 3, 4, 5])
На первый взгляд может показаться, что мы получили копию — оператор is показывает, что это разные объекты, а изменение элемента затронуло лишь значение переменной y
В данном случае вроде все нормально. Но проблема заключается в том, что списки в языке
Python могут иметь неограниченную степень вложенности. Рассмотрим это на примере:
>>> x = [1, [2, 3, 4, 5]] # Создали вложенный список
>>> y = list(x) # Якобы сделали копию списка
>>> x is y # Разные объекты
False
>>> y[1][1] = 100 # Изменяем элемент
>>> x, y # Изменение затронуло переменную x!!!
([1, [2, 100, 4, 5]], [1, [2, 100, 4, 5]])
Здесь мы создали список, в котором второй элемент является вложенным списком, после чего с помощью функции list()
попытались создать копию списка. Как и в предыдущем примере, оператор is показывает, что это разные объекты, но посмотрите на результат — изменение переменной y
затронуло и значение переменной x
. Таким образом, функция list()
и операция извлечения среза создают лишь поверхностную копию списка.
Чтобы получить полную копию списка, следует воспользоваться функцией deepcopy()
из модуля copy
:
>>> import copy # Подключаем модуль copy
>>> x = [1, [2, 3, 4, 5]]
>>> y = copy.deepcopy(x) # Делаем полную копию списка
>>> y[1][1] = 100 # Изменяем второй элемент
>>> x, y # Изменился только список в переменной y
([1, [2, 3, 4, 5]], [1, [2, 100, 4, 5]])
Функция deepcopy()
создает копию каждого объекта, при этом сохраняя внутреннюю структуру списка. Иными словами, если в списке существуют два элемента, ссылающиеся на один объект, то будет создана копия объекта, и элементы будут ссылаться на этот новый объект, а не на разные объекты:
>>> import copy # Подключаем модуль copy
>>> x = [1, 2]
Глава 8. Списки, кортежи, множества и диапазоны
145
>>> y = [x, x] # Два элемента ссылаются на один объект
>>> y
[[1, 2], [1, 2]]
>>> z = copy.deepcopy(y) # Сделали копию списка
>>> z[0] is x, z[1] is x, z[0] is z[1]
(False, False, True)
>>> z[0][0] = 300 # Изменили один элемент
>>> z # Значение изменилось сразу в двух элементах!
[[300, 2], [300, 2]]
>>> x # Начальный список не изменился
[1, 2]
8.2. Операции над списками
Обращение к элементам списка осуществляется с помощью квадратных скобок, в которых указывается индекс элемента. Нумерация элементов списка начинается с нуля. Выведем все элементы списка:
>>> arr = [1, "str", 3.2, "4"]
>>> arr[0], arr[1], arr[2], arr[3]
(1, 'str', 3.2, '4')
С помощью позиционного присваивания можно присвоить значения элементов списка каким-либо переменным. Количество элементов справа и слева от оператора
=
должно сов- падать, иначе будет выведено сообщение об ошибке:
>>> x, y, z = [1, 2, 3] # Позиционное присваивание
>>> x, y, z
(1, 2, 3)
>>> x, y = [1, 2, 3] # Количество элементов должно совпадать
Traceback (most recent call last):
File "
", line 1, in
ValueError: too many values to unpack (expected 2)
В Python 3 при позиционном присваивании перед одной из переменных слева от операто- ра
=
можно указать звездочку. В этой переменной будет сохраняться список, состоящий из
«лишних» элементов. Если таких элементов нет, список будет пустым:
>>> x, y, *z = [1, 2, 3]; x, y, z
(1, 2, [3])
>>> x, y, *z = [1, 2, 3, 4, 5]; x, y, z
(1, 2, [3, 4, 5])
>>> x, y, *z = [1, 2]; x, y, z
(1, 2, [])
>>> *x, y, z = [1, 2]; x, y, z
([], 1, 2)
>>> x, *y, z = [1, 2, 3, 4, 5]; x, y, z
(1, [2, 3, 4], 5)
>>> *z, = [1, 2, 3, 4, 5]; z
[1, 2, 3, 4, 5]
146
Часть I. Основы языка Python
Так как нумерация элементов списка начинается с
0
, индекс последнего элемента будет на единицу меньше количества элементов. Получить количество элементов списка позволяет функция len()
:
>>> arr = [1, 2, 3, 4, 5]
>>> len(arr) # Получаем количество элементов
5
>>> arr[len(arr)-1] # Получаем последний элемент
5
Если элемент, соответствующий указанному индексу, отсутствует в списке, возбуждается исключение
IndexError
:
>>> arr = [1, 2, 3, 4, 5]
>>> arr[5] # Обращение к несуществующему элементу
Traceback (most recent call last):
File "
", line 1, in
IndexError: list index out of range
В качестве индекса можно указать отрицательное значение. В этом случае смещение будет отсчитываться от конца списка, а точнее — чтобы получить положительный индекс, значе- ние вычитается из общего количества элементов списка:
>>> arr = [1, 2, 3, 4, 5]
>>> arr[-1], arr[len(arr)-1] # Обращение к последнему элементу
(5, 5)
Так как списки относятся к изменяемым типам данных, мы можем изменить элемент по индексу:
>>> arr = [1, 2, 3, 4, 5]
>>> arr[0] = 600 # Изменение элемента по индексу
>>> arr
[600, 2, 3, 4, 5]
Кроме того, списки поддерживают операцию извлечения среза, которая возвращает указан- ный фрагмент списка. Формат операции:
[<Начало>:<Конец>:<Шаг>]
Все параметры не являются обязательными. Если параметр
<Начало>
не указан, использует- ся значение
0
. Если параметр
<Конец>
не указан, возвращается фрагмент до конца списка.
Следует также заметить, что элемент с индексом, указанным в этом параметре, не входит в возвращаемый фрагмент. Если параметр
<Шаг>
не указан, используется значение
1
. В ка- честве значения параметров можно указать отрицательные значения.
Теперь рассмотрим несколько примеров:
сначала получим поверхностную копию списка:
>>> arr = [1, 2, 3, 4, 5]
>>> m = arr[:]; m # Создаем поверхностную копию и выводим значения
[1, 2, 3, 4, 5]
>>> m is arr # Оператор is показывает, что это разные объекты
False
Глава 8. Списки, кортежи, множества и диапазоны
147
затем выведем символы в обратном порядке:
>>> arr = [1, 2, 3, 4, 5]
>>> arr[::-1] # Шаг -1
[5, 4, 3, 2, 1]
выведем список без первого и последнего элементов:
>>> arr[1:] # Без первого элемента
[2, 3, 4, 5]
>>> arr[:-1] # Без последнего элемента
[1, 2, 3, 4]
получим первые два элемента списка:
>>> arr[0:2] # Символ с индексом 2 не входит в диапазон
[1, 2]
а так получим последний элемент:
>>> arr[-1:] # Последний элемент списка
[5]
и, наконец, выведем фрагмент от второго элемента до четвертого включительно:
>>> arr[1:4] # Возвращаются элементы с индексами 1, 2 и 3
[2, 3, 4]
С помощью среза можно изменить фрагмент списка. Если срезу присвоить пустой список, то элементы, попавшие в срез, будут удалены:
>>> arr = [1, 2, 3, 4, 5]
>>> arr[1:3] = [6, 7] # Изменяем значения элементов с индексами 1 и 2
>>> arr
[1, 6, 7, 4, 5]
>>> arr[1:3] = [] # Удаляем элементы с индексами 1 и 2
>>> arr
[1, 4, 5]
Объединить два списка в один список позволяет оператор
+
. Результатом объединения будет новый список:
>>> arr1 = [1, 2, 3, 4, 5]
>>> arr2 = [6, 7, 8, 9]
>>> arr3 = arr1 + arr2
>>> arr3
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Вместо оператора
+
можно использовать оператор
+=
. Следует учитывать, что в этом случае элементы добавляются в текущий список:
>>> arr = [1, 2, 3, 4, 5]
>>> arr += [6, 7, 8, 9]
>>> arr
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Кроме рассмотренных операций, списки поддерживают операцию повторения и проверку на вхождение. Повторить список указанное количество раз можно с помощью оператора
*
, а выполнить проверку на вхождение элемента в список позволяет оператор in
:
148
Часть I. Основы языка Python
>>> [1, 2, 3] * 3 # Операция повторения
[1, 2, 3, 1, 2, 3, 1, 2, 3]
>>> 2 in [1, 2, 3, 4, 5], 6 in [1, 2, 3, 4, 5] # Проверка на вхождение
(True, False)
8.3. Многомерные списки
Любой элемент списка может содержать объект произвольного типа. Например, элемент списка может быть числом, строкой, списком, кортежем, словарем и т. д. Создать вложен- ный список можно, например, так:
>>> arr = [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ]
Как вы уже знаете, выражение внутри скобок может располагаться на нескольких строках.
Следовательно, предыдущий пример можно записать иначе:
>>> arr = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
Чтобы получить значение элемента во вложенном списке, следует указать два индекса:
>>> arr[1][1]
5
Элементы вложенного списка также могут иметь элементы произвольного типа. Количество вложений не ограничено, и мы можем создать объект любой степени сложности. В этом случае для доступа к элементам указывается несколько индексов подряд:
>>> arr = [ [1, ["a", "b"], 3], [4, 5, 6], [7, 8, 9] ]
>>> arr[0][1][0]
'a'
>>> arr = [ [1, { "a": 10, "b": ["s", 5] } ] ]
>>> arr[0][1]["b"][0]
's'
8.4. Перебор элементов списка
Перебрать все элементы списка можно с помощью цикла for
:
>>> arr = [1, 2, 3, 4, 5]
>>> for i in arr: print(i, end=" ")
1 2 3 4 5
Следует заметить, что переменную i
внутри цикла можно изменить, но если она ссылается на неизменяемый тип данных (например, на число или строку), это не отразится на исход- ном списке:
>>> arr = [1, 2, 3, 4] # Элементы имеют неизменяемый тип (число)
>>> for i in arr: i += 10
>>> arr # Список не изменился
[1, 2, 3, 4]