Мы продолжаем разговор про упорядоченные типы данных. Мы поговорим про то, как обратиться к элементу по индексу, про новый для нас тип данных — кортеж и введем два важных понятия: изменяемые и неизменяемые типы данных. На самом деле, обращаться к элементам по индексу мы уже умеем. Когда мы работали со строками, мы говорили про то, что все символы находятся в определенном порядке. Именно поэтому строки мы видим не перемешанными, а какие-то осмысленные слова, если, естественно, мы их создали как какие-то осмысленные слова. Например, мы можем посмотреть на нашу строчку "Hello, world", и если бы я вас спросила, какой здесь первый символ, вы бы мне все ответили, что это заглавная "H". Точно так же компьютер знает, на каком месте находится какой символ строки. Например, под нулевым индексом находится та же самая заглавная буква "H", и мы с вами говорили о том, что компьютер считает так же, как мы, но с нуля — об этом мы помним. Мы также говорили о том, что есть еще отрицательная индексация. Мы можем обращаться к символам строки по отрицательным индексам, когда это удобнее, например, чтобы достать последний символ здесь, я могу не высчитывать, что он 12 от начала, а могу обратиться к минус первому индексу и получу восклицательный знак. Точно так же Python работает со списками и с другими последовательностями. Например, наш любимый список покупок: "хлеб", "молоко", "сметана" — три элемента, три индекса 0, 1, 2. Соответственно, если я попрошу Python из этого списка достать мне элемент под нулевым индексом, я получу "хлеб". Точно так же работает отрицательная индексация. Если я попрошу элемент под минут третьим индексом, я тоже получу "хлеб", то есть единственная разница, что теперь я получаю не отдельные символы, даже если это у меня список строк, а я получаю именно мой элемент: строку, число, логическую переменную или даже что-то другое. Можно сравнить хранение списков с гардеробом. Например, вы приходите в гардероб и сдаете свою куртку, получаете номерок — первый, второй, третий, 125. Когда вы приходите с этим номером обратно, гардеробщик в идеальном случае подает вашу куртку. Точно так же и Python — вы говорите элемент под каким номером вы хотите получить, и он вам его выдает. Следующую задачу, которую мы научимся решать, этот красивый вывод списков. Когда в прошлом видео мы работали со списками в Python, вы видели, что когда мы их печатали, мы их печатали со всей технической информацией сразу. Что я здесь имею в виду — выводились вот эти скобки, которые ограничивают список, запятые, которые разделяют элементы, кавычки, которые ограничивают строки. Если у нас, например, список строк, наверное, это не то, что мы хотим видеть в выводе, если мы хотим сделать его каким-то аккуратным. Например, мне было бы интересно напечатать мой список покупок через пробел или, может быть, через запятую, чтобы пользователь видел, что я туда записала. Такую задачу можно решить несколькими способами. Самый и пока единственный очевидный для нас — это перечислить отдельные элементы списков как отдельные элементы, которые мы передаем функции "print()". Итак, теперь я аргументам передаю не список, а передаю отдельно первый элемент списка, затем второй. Напечаталось "хлеб", "молоко". Если бы я добавила функцию "print()" разделитель, они бы напечатались, например, через запятую, но, мне кажется, очевидно, что если у нас какой-то большой список, то этот способ не выглядит очень удобным. Здесь на помощь нам приходит оператор распаковки. На самом деле, мы уже встречались с таким символом — это звездочка, мы ее использовали, например, в умножении, когда мы умножали число на число или строку на число, чтоб повторить ее какое-то количество раз. Здесь мы его используем в непривычной для нас роли. Посмотрите, у меня в функции "print()" аргументом является сейчас список, и перед ним стоит звездочка. Почему она называется здесь оператором распаковки, потому что она как будто бы раскрывает список и говорит функции "print()": пожалуйста, не печатай мне его как один объект, а возьми каждый элемент из этого контейнера и считай, что это отдельный аргумент. По сути можно представить, что функция "print()", на моем втором примере кода, видит наш список на самом деле как перечень отдельных элементов, как код, который выше. Соответственно, мы можем добавить разделитель и, например, напечатать наш список покупок через запятую, тире, через что угодно, если честно. Следующий тип данных, о котором мы поговорим, — это кортеж. Давайте посмотрим на его синтаксис. Мы ставим круглые скобки, круглые скобки — это сигнал для Python, что сейчас мы будем перечислять элементы, которые нужно сложить в какой-то контейнер. Этот контейнер — кортеж. Очень похоже на то, что мы делали со списком, поменялся только тип скобок. Такой тип данных в Python называется "tuple()" и, соответственно, в англоязычной документации тоже. Когда же мы используем кортеж и чем он отличается от списка? Самое главное свойство кортежа в том, что он не изменяемый. Мы с вами в прошлом видео говорили про то, что мы можем создать пустой список, и потом мы научимся добавлять в него элементы. С кортежем такие фокусы не пройдут. Кортеж, каким мы его создали, таким он и будет. Это иногда удобно, чтобы хранить данные, которые вы не хотите случайно изменить, или иногда некоторые функции, которые мы встретим позже в нашем курсе, будут нам отдавать как раз элемент в виде кортежа, поэтому было бы здорово, если бы мы его узнавали и знали, какими свойствами он обладает. Все остальное у кортежа, как у списков. Мы поговорим про какие-то операции, которые будут применяться к спискам, и многие из них будут применяться к кортежу. Мы говорили о том, что в последовательностях мы можем обратиться к элементу по индексу и мы можем обратиться к элементу по индексу в кортежах. Раз мы уже произнесли эти слова: изменяемый — неизменяемый, то давайте поговорим о том, что это такое. Список — изменяемый тип данных. Что это значит? Это значит, что мы можем добавлять список элементов, мы научимся делать это позже, или мы можем заменить элемент внутри списка. Например, давайте посмотрим на код. Здесь я создаю мой список покупок и, представим, что вы передумали покупать "хлеб", а решили купить на самом деле "батон". Что я делаю — я обращаюсь к элементу по его индексу, мы помним, мы с вами видели, несколько слайдов назад, что если мы обратимся к нулевому элементу, мы получим "хлеб". Я обращаюсь к этому элементу по индексу и заменяю его значение на "батон". Вывожу — и действительно там теперь "батон", печатаю полный список — и я получаю измененный список. Там больше нет "хлеба", есть "батон", "молоко" и "сметана". Список позволяет проделать такую операцию, я могу обратиться к элементу по индексу и изменить его значение, а вот кортеж, как мы с вами уже сказали, неизменяемый тип данных. При попытке заменить элемент в кортеже, мы получим ошибку. Смотрите, теперь у меня мой список покупок, но он хранится в кортеже, я делаю ту же самую операцию, пытаясь заменить "хлеб" на "батон", но получаю ошибку. Ошибка у нас "Type error", и она буквально переводится, что тип данных кортеж не поддерживает изменение элемента через операцию присвоения. Ведь по сути, что мы делаем, мы присваиваем новое значение элементу под этим индексом, точно так же, как мы присваивали новое значение каким-то переменным. На самом деле, мы знаем еще один неизменяемый тип данных, ведь строка тоже не изменяемая, она тоже последовательность — мы можем обратиться к элементу по индексу, по его порядковому номеру, но если я, например, попытаюсь изменить букву в строке, например, я хочу заменить строчную "ч" на заглавную "Ч", я получу точно такую же ошибку как со кортежем. Она тоже звучит "Type error", единственное отличие, что в ней написано, что теперь строка не поддерживает присвоение элементов. Иногда у нас возникает такая ситуация, когда мы работаем с кортежем, и нам в нем нужно изменить элемент. Что же делать? На самом деле, у нас есть функции, которые могут, например, из кортежа сделать список или из списка — кортеж. Эта функция "list()" и "tuple()". Мы с вами с подобным уже встречались, например, когда у нас какое-то число было представлено строкой, мы использовали функцию "int()", чтобы превратить эту строку в целое число и дальше с ним работать, или float, чтобы превратить его в вещественное. Здесь точно так же, представим, что нам нужно изменить элемент кортежа, мы можем функции "list()" передать кортеж как аргумент — и он превратится в список, сохраним его в отдельную переменную и изменим в нем элемент, или у нас был какой-то список, и мы знаем, что дальше мы не будем его изменять и хотим защитить его от этих случайных изменений. Передаем функции "tuple()" список как аргумент — и получаем кортеж. Изменяемость и неизменяемость данных очень важный концерт, позже мы увидим, что какие-то данные смогут играть разные роли в каких-то ситуациях, поэтому важно помнить, какие типы мы можем изменить, а какие — нет. Итак, мы с вами поговорили про индексацию элементов и посмотрели на то, что она работает почти как со строками. Мы поговорили про новый тип данных — кортеж, и мы поговорили про изменяемость и неизменяемость. Пока мы напоминаем, что изменяемый тип данных мы знаем только один, — это список, а неизменяемые все другие: целое число, вещественные, логическая переменная, строка и кортеж. Давайте теперь посмотрим, как с этим работать в Python.