уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.

Продолжаю разбираться с типами данных в Python и попутно — в Delphi 10.3, т.к. пока Python для меня — это «непознанный зверь», а в Delphi достаточно всяких проектов больших и малых которые хотя бы и для личного пользования, но надо поддерживать.
Итак, сегодня на повестке дня — списки (list) в Python. Список в Python — это упорядоченная последовательность элементов. А, как я говорил ранее, в Python всё — объекты. При этом списки относятся к изменяемым типам данных, то есть мы можем не только получить элемент списка по его индексу, но и изменить его. Но, обо всем по порядку.Итак, что же представляет собой список в Python, если рассматривать его с позиций Delphi? Список Python — это ни что иное, как обычный динамический массив. Например, в Delphi с некоторых пор мы можем задать массив и перечислить его элементы вот так:

var arr: array of integer;
    I: Integer;
begin
  arr:=[4,5,6];
  for I := Low(arr) to High(arr) do
    OutputDebugString(PChar(IntToStr(arr[i])));
end;

т.е. объявили динамический массив и присвоили ему три значения. В итоге индексы элементов у нас стали, соответственно, 0, 1 и 2. И теперь мы можем изменять элементы созданного массива, просто обращаясь к ним по индексу:

arr[1]:=6;
arr[0]:=6;

Собственно, тоже самое можно делать и в Python со списками — создавать, обращаться к элементу по его индексу и изменять элементы:

>>> arr = [4,5,6]
>>> arr
[4, 5, 6]
>>> arr[0] = 6
>>> arr[1] = 6
>>> arr
[6, 6, 6]

Что же отличает список в Python от массива в Delphi?

1. Создание списков в Python

Если в Delphi мы обязаны объявить переменную, указать тип элементов массива и потом заполнить его элементами заданного типа, то в Python есть специальная функция — list(), которая преобразует любую последовательность в список. Например, вот такую нехитрую в Python операцию повторить без лишних телодвижений в Delphi не получится:

>>> arr2 = list("String")
>>> arr2
['S', 't', 'r', 'i', 'n', 'g']

Здесь все просто. Строка — это упорядоченная последовательность символов. Соответственно, передавая строку в функцию List(), на выходе мы получаем список где каждый его элемент — это отдельный символ строки.
Далее, в Python нам никто не запрещает объявлять список с разными типами элементов, перечислив их в квадратных скобках:

>>> arr4 = ['Строка', 1, 2, 3, '4']
>>> arr4
['Строка', 1, 2, 3, '4']

С одной стороны кажется, что это нехорошо — давать записывать в список разные типы данных, но, с другой стороны — почему бы и нет? Я бы сказал, что это не нехорошо, а, скорее — непривычно после Delphi. Надо просто привыкнуть к таким особенностям языка.
Третий способ создания списка — заполнение поэлементно, например, вот так:

>>> arr5 = list() #Создали пустой список
>>> arr5.append(1) #Добавили в список число
>>> arr5.append('Строка');#Добавили в список строку
>>> arr5
[1, 'Строка']

Как вы понимаете, в нынешней версии Delphi также есть подобная возможность при работе с динамическими массивами, правда, реализуется она несколько иначе:

var arr: array of integer;
begin
  arr:=[1];
  arr:=arr+[2];
  arr:=arr+[3];
end;

2. Работа со списками в Python

2.1. Присвоение значений элементам списка

Выше я уже указал, что изменять элементы списка мы можем также, как и в Delphi — обратиться к элементу по индексу и присвоив необходимое значение. Однако, мы не можем добавить к списку новый элемент, указав в качестве индекса число, превышающее последний индекс:

>>> arr[3] = 5
Traceback (most recent call last):
  File "<pyshell#31>", line 1, in <module>
    arr[3] = 5
IndexError: list assignment index out of range

При работе с переменными типа list также следует иметь в виду, что в переменной сохраняется не сам объект, а ссылка на него. Эта особенность хорошо демонстрируется при групповом присваивании значений переменной (которого, кстати, нет в Delphi, но было бы неплохо иметь):

>>> x=y=[1,2]
>>> x = y = [1,2] 
>>> x,y
([1, 2], [1, 2])
>>> x[0] = 100
>>> x,y
([100, 2], [100, 2])

Как видно из примера, в результате мы создали две переменные, которые ссылаются на один и тот же объект, а не два разных объекта. Кстати говоря, возвращаясь к теме работы со строками в Python, такая бы возможность (групповое присвоение значения переменным) при работе со строками сработала бы:

>>> s1 = s2 = "String"
>>> s1=s1*3
>>> s1
'StringStringString'
>>> s2
'String'

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

2.2. Создание копий списка

Итак, определились, что групповое присвоение значений не создает разные копии списков, соответственно, и такая запись не приведет к успеху, если нам необходимо создать копию:

>>> a = [1,2,3]
>>> b = a
>>> a is b
True

Как идите, a и b — один и тот же объект.
В Delphi 10.3, кстати, то же самое:

var arr, arr2: array of integer;
    I: Integer;
begin
  arr:=[1,2,3]; //создали массив на три элемента
  arr2:=arr;
  arr2[0]:=100;
  //перечисляем все элементы массива
  for I := Low(arr) to High(arr) do
    begin
      OutputDebugString(PChar('arr '+IntToStr(arr[i])));
      OutputDebugString(PChar('arr2 '+IntToStr(arr2[i])));
    end;
end;

Здесь в итоге, оба первых элемента массивов в итоге будут равны 100.
Чтобы создать копию списка в Python можно:
1. Воспользоваться уже известной нам функцией list():

>>> a = [1,2,3]
>>> b = list(a)
>>> a, b
([1, 2, 3], [1, 2, 3])
>>> a is b
False

2. Создать срез:

>>> a = [2,3,4]
>>> b = a[:]
>>> a is b
False

Срез — очень полезная и интересная возможность Python для которой я сходу даже не могу припомнить аналогов в Delphi и про которую я планирую даже сделать отдельный пост.
3. Воспользоваться функцией copy():

>>> a = [5,6,7]
>>> b = a.copy()
>>> a,b
([5, 6, 7], [5, 6, 7])
>>> a is b
False

Во всех трех случаях мы создали копии списков. Однако и здесь не обходится без «подводных камней». Как говорилось выше, список Python аналогичен динамическому массиву в Delphi. Соответственно, никто нам не запрещает делать вложенные списки, или, говоря в терминах Delphi — многомерные массивы. Например, можно создать вот такой список:

>>> a = [[1,2],[3,4]]
>>> a
[[1, 2], [3, 4]]

где каждый элемент списка — это ещё один список на два элемента. Теперь сделаем копию этого списка и попробуем в копии изменить какой-нибудь элемент вложенного списка, например, вот так:

>>> b = a.copy()
>>> a is b
False
>>> b[0][0]=100
>>> a
[[100, 2], [3, 4]]
>>> b
[[100, 2], [3, 4]]

Как видите «что-то пошло не так». Вроде бы и проверка показала, что переменные ссылаются на разные объекты, но изменение в списке b привело к изменению в списке a. Получается, что мы создали не полную копию списка, а копию «поверхности» (первого уровня, первого измерения — как угодно), а вот то, что было глубже — оставили ссылки на объекты. Чтобы создать полную копию списка необходимо воспользоваться функцией deepcopy() из модуля copy:

>>> a = [[1,2],[1,2]]
>>> import copy
>>> b = copy.deepcopy(a)
>>> a is b
False
>>> b[0][0] = 100
>>> a,b
([[1, 2], [1, 2]], [[100, 2], [1, 2]])

Функция deepcopy() создает копию каждого объекта и, при этом, сохраняет внутреннюю структуру списка.

2.3. Различные функции работы со списками

1. len() — определение длины списка:

>>> x = [1,2,3]
>>> len(x)
3

У объекта list определены следующие методы:
2. count(x) — подсчет количества элементов, равных x:

>>> x = [1,1,2,3,1,1]
>>> x.count(1)
4

3. extend(x) — добавление в конец списка последовательности x:

>>> x = [1,1,2,3,1,1]
>>> x.extend("Строка")
>>> x
[1, 1, 2, 3, 1, 1, 'С', 'т', 'р', 'о', 'к', 'а']

4. index(x) — поиск наименьшего индекса элемента, который равен x
Для демонстрации воспользуемся предыдущим примером:

>>> x
[1, 1, 2, 3, 1, 1, 'С', 'т', 'р', 'о', 'к', 'а']
>>> x.index(1)
0 #самый первый элемент со значением 1 находится в самом начале списка
>>> x.index("С")
6 #элемент со значением "С" находится на седьмой позиции и имеет индекс 6

5. insert(i, x) — вставка элемента x в i-ю позицию:

>>> z = [0,1,3]
>>> z.insert(2,2)
>>> z
[0, 1, 2, 3]

6. pop(i) — возвращает i-й элемент, удаляя его из последовательности:

>>> z = [0,1,3]
>>> z.insert(2,2)
>>> z
[0, 1, 2, 3]
>>> y = z.pop(0)
>>> y
0
>>> z
[1, 2, 3]

7. reverse() — меняет порядок элементов на обратный:

>>> z
[1, 2, 3]
>>> z.reverse()
>>> z
[3, 2, 1]

8. sort() — сортирует элементы списка:

>>> z
[3, 2, 1]
>>> z.sort()
>>> z
[1, 2, 3]

Вот, пожалуй, на сегодня и всё. Что осталось «за бортом»:
1. перебор элементов списка различными способами
2. генераторы списков и выражения-генераторы
3. различные функции по работе с последовательностями.
Безусловно, по мере продолжения изучения возможностей Python я буду возвращаться к этим вопросам, однако, если вам не терпится рассмотреть эти вопросы прямо сейчас, то можете приобрести одну из книг по Python, которые представлены ниже.

Подведем небольшой итог. Итак, список (list) в Python представляет собой примерно тоже самое, что и динамический массив в Delphi. Вместе с этим, в Python возможности работы со списками несколько богаче в силу особенностей самого языка — можно задавать элементы списка различных типов, копировать списки буквально в одну строку кода, использовать срезу и т.д.

Книжная полка

Автор:Владимир Дронов
Название: Python 3. Самое необходимое
Описание Описан базовый синтаксис языка Python 3: типы данных, операторы, условия, циклы, регулярные выражения, встроенные функции, классы и объекты, итераторы и перечисления, обработка исключений, часто используемые модули стандартной библиотеки
Купить на ЛитРес
Автор: Майк МакГрат
Название: Python. Программирование для начинающих
Описание: Книга «Программирование на Python для начинающих» является исчерпывающим руководством для того, чтобы научиться программировать на языке Python. В этой книге с помощью примеров программ и иллюстраций, показывающих результаты работы кода, разбираются все ключевые аспекты языка. Установив свободно распространяемый интерпретатор Python, вы с первого же дня сможете создавать свои собственные исполняемые программы!
Купить на ЛитРес
уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
5 2 голоса
Рейтинг статьи
Подписаться
Уведомить о
0 Комментарий
Межтекстовые Отзывы
Посмотреть все комментарии