Вначале стоит сказать, что Python - это язык, который может занять у Тебя довольно много времени, чтобы изучить все его детали. С другой стороны, хорошая новость заключается в том, что Тебе не нужно с этого начинать. Чтобы приступить к решению некоторых задач, Тебе нужно знать только часть языка (а толку знать что-то больше, если не можешь это применить?). Напомню еще раз о правиле - 20% усилий и 80% выгоды (ценности). Можешь пойти еще дальше и возвести эти значения в квадрат. Тогда оказывается, что только 4% усилий могут принести целых 64% ценности!

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

Звучит круто? Итак, приступим!


ПОШАГОВОЕ ВИДЕО ДЛЯ ПЕРВОГО УРОКА:
Переменная

Сначала мы увидим, как в Python создаются переменные.
Код

my_var = 1
my_var - это имя переменной. Когда дело доходит до наименования, имеет смысл использовать английский язык. Почему? Потому что это такой стандарт :). Здесь нужно было бы копнуть еще глубже, но исторически так сложилось, что английский стал стандартом в ИТ. Также как исторически сложилось, что доллар стал мировой валютой. Здесь можно долго дискутировать а почему именно так, но факт остается фактом. Советую придерживаться этого стандарта. Здесь стоит еще отметить очень важную особенность английского языка. Я его иногда называю "техническим языком". Почему? Ведь в отличие, например, от русского языка, в английском очень важен порядок слов и в целом очень сильно ограничен способ выражения мыслей (и состояния души) и там, например, нет таких конструкций как "да нет наверное". Это нереально перевести на английский, да и сама конструкция мало логичная - но тем не менее "нам" понятно. Иными словами, английский язык очень хорошо подходит для машин - он простой и понятный (читается, как алгоритм - машины такое любят).

Еще одна особенность, раз уж заговорил про стандарты. Писать можно код по-разному, но есть проблемка. Ведь код не только нужно написать, но и потом его нужно "поддерживать". Каждый опытный программист знает, что поддержка кода - это куда более дорогие события, чем его создание. Именно поэтому "старожилы" (их еще называют senior) стараются писать код как можно проще.

Кстати, новички наоборот - сам проходил этот период "максимализма" в программировании, когда думал, что я кажусь "умнее", если напишу трудно понятный код, а сейчас думаю совсем наоборот. Есть такая поговорка:
Каждый идиот может создать машину, которой сможет управлять только гений. И только гений создаст машину, которой сможет управлять каждый идиот.
В программировании что-то похожее. Чтобы этот процесс оценки стиля кода сделать объективным, появился стандарт - PEP8. Не со всеми пунктами стандарта обязательно нужно согласиться, но все же стоит заметить, что есть там много полезных пунктов. Нам сейчас достаточно знать о том, что такой стандарт существует - по ходу дела можно будет в него углубиться, так что не переживай, что там много букв и как со всем этим справиться (кстати, возможно, это не так очевидно, но в любом государстве существует множество "правил", о которых даже не знаешь и это не мешает в нем жить, здесь похожий принцип - всему свое время).

Также стоит отметить, что есть несколько слов, которые ни при каких обстоятельствах НЕ должны использоваться в качестве имен переменных. К таким словам относятся: `print`, `list`, `set`, `dict` и т. д. Это ключевые слова, которые Python использует для своих собственных встроенных функций. Их не так уж и много, но, к счастью, Тебе не нужно их все запоминать. Если мы используем зарезервированные слова, `jupyter` автоматически "окрашивает" эти слова в зеленый, поэтому Тебе просто нужно внимательно следить за цветами ;).

На этом этапе мы присвоили значение цифры `1` переменной `my_var`. Обрати внимание, что здесь нет `";"` в конце строки (как это обычно бывает в C ++ и подобных языках). Хотя можешь поставить, если хочешь и если привычка такая уже имеется (со временем пройдет, но это не точно), однако это необязательно.

Для лучшего понимания переменной, предлагаю такую ассоциацию. Переменная - это область памяти, напоминающая ячейку в банке или коробку, в которой мы можем что-то хранить. Чтобы найти из множества ячеек нужную, мы подписываем наши ячейки, в данном случае мы подписали как `my_var`, а вообще желательно, чтобы имя переменной отражало ее суть. Например, в коробке с надписью "соль" мы ожидаем увидеть соль, а в коробке с надписью "сахар", мы ожидаем увидеть сахар. Содержимое коробки может быть разным, например: `1`, `5`, `3.1415`,`"велосипед"` - это значения переменных, в нашем случае - это `1`.
Теперь выведем на экран содержимое переменной. Для этого мы используем функцию `print()`.
Код

print(my_var)
Результат: 1

Важно знать

1. Имя переменной не может начинаться с цифры
2. В имени переменной используй только латинские буквы `a-z`, `A-Z`, `цифры` и `символ нижнего подчеркивания (_)`
3. Python — это язык, чувствительный к регистру. Переменная `my_var` и `My_var` — это две совершенно разные переменные. Для присвоения имени переменных принято использовать стиль lower_case_with_underscores (слова из маленьких букв с подчеркиваниями).

Задание 1.2.1
Создай новую переменную (дай ей другое имя) и выпиши её содержимое на экран. Кстати, в материалах курсов для заданий даются подсказки и готовые решения, но по умолчанию они скрыты :).


Заметки на полях

Что такое комментарий? Это некоторая информация для разработчика (обычно это пояснение), но что важно - комментарии игнорируются при запуске кода. Комментарии иногда можно использовать и по-другому - если у Тебя есть несколько строк кода и Ты не хочешь, чтобы они выполнялись, просто добавь `#` в начало строки. Стоит отметить, что каждая строка кода требует отдельного добавления знака `#`. Кроме того, не имеет значения, сколько символов `#` мы используем. Достаточно одного, и тогда все, что стоит за ним, будет проигнорировано при запуске кода (иногда добавляются другие, например, для облегчения чтения комментариев). Хотя, сразу замечу, что оставлять куски закомментированного кода "на потом", это плохая привычка. Ведь это будет создавать только шум, тогда, возможно, стоит удалить такой код?
Типы переменных

Int

Ты уже знаешь, как создать переменную. Теперь пора рассмотреть типы переменных. Но сначала давай рассмотрим функцию `type ()`, которая позволяет узнать, к какому типу относится переменная. Давай проверим.
Код

type(my_var)
Результат: int

Как видишь, переменная имеет тип `int`, что является сокращением от `integer` (на английском языке это просто означает целое число. Это такие числа, как: 1, 2, 10, но также и целые отрицательные числа, например: -1. -5 или -245 и т.д.).

Float

Следующий тип переменной, которую обязательно стоит знать, - это `float`, т.е. число с плавающей запятой . Что это означает? Это переменная, которую мы применяем, когда хотим использовать десятичные числа, например, как мы хотим записать температуру (`36.6`) или средний балл (`4.9`). Обрати внимание, что мы добавляем точку (`.`), а не запятую (`, `). Этот стандарт из США (про стандарт ИТ уже писал выше - так исторически сложилось).


Проверяем.
Код

my_temp = 36.6
type(my_temp)
Результат: float


Boolean

Это логическая переменная с двумя состояниями `True` или `False`. Кстати, иногда говорят `bool`, как сокращение от `boolean`.
Код

is_good = True
print(is_good)
type(is_good)
Результат: True, bool



Обрати внимание, что `True` или `False` пишутся с заглавной буквы (в других языках часть пишут с маленькой буквы, в Питоне - это своя особенность).


List

По-русски это называется список. Довольно часто нам нужно написать последовательность цифр (или символов), например, перечислить оценки в группе. Предположим, группа состоит из пяти человек с оценками: `4, 5, 5, 3, 4`.


Для того чтобы создать список, нужно использовать квадратные скобки `[]`. Первая скобка `[` открывает список, затем идет содержимое через запятую и в конце закрываем список `]`. Обрати внимание на то, что скобки квадратные, это важно! Если мы напишем с круглыми скобами `(4, 5, 5, 3, 4)` - это тоже заработает, но будет иметь другой смысл (о круглых скобках еще поговорим).
Код

group_scores = [4, 5, 5, 3, 4]

print(group_scores)
type(group_scores)
Результат: [4, 5, 5, 3, 4], list




Как видишь, мы присвоили список рейтингов переменной с названием `group_scores`. На данный момент этот список (англ. `list`) состоит из пяти элементов: `4, 5, 5, 3, 4`

Можешь спросить, а как я могу получить доступ к отдельным значениям списка? Ответ: с помощью индексов. У каждого элемента в списке есть свой индекс (грубо говоря - номер ячейки в списке), с помощью которого мы можем перейти к заданному значению. Помни, что индексирование начинается с «0»! Для программистов это нормально (говорят, даже что некоторые программисты начинают считать детей с нуля, но это не точно) Другими словами, если хочешь увидеть первый элемент в списке, делаешь так: `group_scores [0]`.

Давай проверим.
Код

group_scores[0]
Результат: 4




Задание 1.2.2

Твоя задача - "добраться" до четвертого элемента в списке (результат должен быть `3`).
Задание 1.2.3

Твоя задача - добраться до последнего элемента в списке (предположим, не знаешь, сколько элементов в списке).
Полезно знать!

Индекс также может быть отрицательным числом, например -1, -2, -3 и т. д. Например, -1 значит, что это последний элемент. Почему так? Длинная версия, чтобы получить доступ к последнему элементу `group_scores[len(group_scores) - 1]` более короткая версия (которую советую использовать) будет - `group_scores[-1]`. Результат будет идентичен.

Срезы
Также возможно вырезать часть списка из списка.

Синтаксис: `[start_index: stop_index]`. Это полуинтервал закрытый слева и открытый справа `[a, b)`. Другими словами, на выходе будут элементы с индексами от `start_index` до `stop_index - 1`.

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

group_scores
Результат: [4, 5, 5, 3, 4]





Код

group_scores[1:5] # мы начинаем со второго значения (т.е. start_index = 1) и заканчиваем пятым (с индексом 4)
Результат: [5, 5, 3, 4]






Код

group_scores[2:5] # мы начинаем с третьего значения (т.е. start_index = 2) и заканчиваем пятым (с индексом 4)
Результат: [5, 3, 4]






Полезно знать!

Если мы пропустим `start_index`, то интерпретатор подставит туда 0. Если мы пропустим `stop_index`, он подставит результат использования `len()` .

С помощью оператора `==` мы можем сравнивать, имеют ли две переменные одинаковые значения. Кстати обрати внимание, что там два раза `"="`. Почему нельзя сравнивать с помощью одного `=`? Поскольку один знак `=` используется для присвоения значения имени переменной. Это важно отличать!

Проверяем.
Код

group_scores[:3] == group_scores[0:3] # списки идентичны
Результат: True

Код

group_scores[2:] == group_scores[2:len(group_scores)] # списки идентичны
Результат: True


Размышляем

Как думаешь, что произойдет, если мы не укажем явно `start_index` и `stop_index`? Я имею в виду такую конструкцию `[:]`, то есть `start_index` и` stop_index` пропускаются.
Код

group_scores[:]
Результат: [4, 5, 5, 3, 4]



Полезно знать!

Результат выглядит идентично, но есть важное "но".. и это нужно знать - в данном случае мы получили копию списка. Физическую копию.

Почему это важно понимать? Дело в том, что ресурсы компьютера ограничены. Особенно когда мы говорим о так называемых больших данных (англ. `big data`). Нам нужно уметь оптимально работать с данными, т.е. понимать основные принципы использования наших ресурсов. Например, те же самые данные можно записать раз (физически) и использовать множество раз логически.

Попробуем лучше разобраться. Опять же, сейчас нет времени на то, чтобы подробно рассказать как устроен компьютер. Но все-таки, стоит ознакомиться с принципом работы памяти `RAM`

Оперативная память (она же RAM) выглядит, примерно, так:
Но я все же, лучше буду использовать аналогию и объясню немного по-другому. Представь, что есть город, что в центре «этого городка» много домов. У каждого дома есть свой адрес (будем называть его `ID`). У каждого дома тоже есть своя вместимость, сколько человек (данных) может там проживать.


В Python есть функция - `id()`, которая возвращает нам этот адрес "дома" или говоря точнее - физический идентификатор переменной (т.е. адрес в RAM - это целое число, похожее на то, как нумеруются дома).

Довольно часто, в целях оптимизации, разные физические переменные хранятся под одним и тем же адресом (включая списки). Однако мы можем скопировать физический контент в другой дом. То, что у нас есть физическая копия, означает, что одна и та же информация находится в разных «домах». По сути это значит, что после копии мы занимаем в 2 раза больше ресурсов.

Количество домов в городе ограничено (площадь города ограничена). В данном случае - это количество «домов» измеряется в байтах.

Пример. Предположим, мы сначала создаем новую переменную `list_a` и содержимое списка ` [1, 2, 3]`
В результате этот список физически хранится в доме номер 3. Адрес можно увидеть с помощью функции id (). Затем мы создаем новую переменную list_b, но она указывает на тот же адрес, что и list_a. Другими словами, изменения содержания дома 3 затронут и list_a и list_b одновременно (ведь они "прописаны" в одном доме). Можешь думать о переменной не как о доме, а о том, что она ведет Тебя к конкретному дому. Смотри картинку.
Однако мы можем сделать физическую копию. Чтобы сделать физическую копию списка, мы используем этот оператор [:]. Предположим, мы делаем физическую копию list_a и записываем её как list_c. Именно тогда содержимое одного дома (в данном случае номер 3) будет перенесено в содержимое другого дома (в данном случае номер 6). Смотри картинку.
А что значат другие (голубые) дома? Это место, где кто-то может подселиться. В момент, когда все дома будут заполнены, а мы попытаемся найти новый - появится знаменитая ошибка MemoryError. Это значит, что свободного места больше нет.

Полезно знать!
Кстати, на собеседованиях любят спрашивать - как можно сделать (физическую) копию списка. Вот уже знаешь :).

Теперь вернемся к group_scores и проведем живой эксперимент.

Код

copy_group_scores = group_scores

id(group_scores), id(copy_group_scores)
Результат: (140570324603456, 140570324603456)




Как видишь, в настоящее время у нас есть две переменные, но они физически назначены одному и тому же объекту (такая особенность Python, что если мы создаем новый список на основе другой переменной, мы не создаем новый объект [используя аналогию выше , это не касается нового дома]).
Если изменишь что-либо в списке copy_group_scores, это также повлияет на списокgroup_scores.

Давай проверим.


Код

copy_group_scores[0] = 100
group_scores
Результат: [100, 5, 5, 3, 4]





Мы изменили первый элемент в copy_group_scores, и это также повлияло на первый элемент в group_scores. Предположим, мы хотим сделать физическую копию списка (создать новый объект с такими же элементами). Для этого мы используем конструкцию с [:].

Давай проверим.

Код

group_scores = [4, 5, 5, 3, 4]
clone_group_scores = group_scores[:]
clone_group_scores[0] = 100

print(group_scores)
id(group_scores), id(clone_group_scores)
Результат:
[4, 5, 5, 3, 4]

(140570324576064, 140570324652800)

Как видишь, group_scores и clone_group_scores - это два разных физических списка (у них разные идентификаторы). Следовательно, после изменения значения в clone_group_scores не было внесено никаких изменений в group_scores (и наоборот).

Добавление нового элемента
Что, если мы хотим добавить совершенно новый элемент, а не изменять существующий?
Добавление значения в существующий список выполняется с помощью функции .append(). Новый элемент появится в конце.

Код

my_list = [1]
print(my_list)
my_list.append(2)
print(my_list)
Результат:
[1]
[1, 2]
Мы также можем вставить элемент в список по определенному индексу с помощью .insert(index, value). Тогда все предметы справа от этой позиции переместятся правее на одно место.

Код

my_list = [1, 8, 4]
print(my_list)
my_list.insert(2, 3)
print(my_list)
Результат:
[1, 8, 4]
[1, 8, 3, 4]

Объединение двух списков
Есть два списка и хочешь их объединить, то можешь использовать +
Код

list_a = [1, 2, 3]
list_b = [4, 5, 6]

list_c = list_a + list_b
list_c
Результат:
[1, 2, 3, 4, 5, 6]
Полезно знать!

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

Код

my_list = [1]
my_list += [2]

print(my_list)
Результат:
[1, 2]

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

Код

my_list = [1, 0.1, "a", 2]
print(my_list)
Результат:
[1, 0.1, 'a', 2]


Set

Так на английском называется множество. У множества есть интересное свойство, заключающееся в том, что оно содержит только уникальные элементы.
Очень полезная штука. Я часто использую его, когда нужно достичь хотя бы одной из трех вещей:
  1. Когда нужно получить уникальный набор элементов (в списке одни и те же значения могут повторяться много раз).
  2. Быстро проверить, принадлежит ли элемент набору.
  3. Математические операции над множествами (соединение, проверка на различие и т.д.).
Множество может быть создано из списка.

Код

my_list = [1, 1, 1, 2]
my_set = set(my_list)

my_set
Результат:
{1, 2}



Обрати внимание на фигурные скобки - {}. В отличие от списка (там квадратные скобки) у множества используются фигурные скобки (кстати, фигурные скобки еще и у словаря - но к нему еще дойдем).
Запомни, что синтаксис set отличается от list тем, что значения множества находятся между {}.
Что еще важно во множестве, так это то, что оно не индексируется! Это означает, что мы не можем извлечь из него какой-либо элемент или диапазон, как мы можем сделать со списком. Если мы хотим это сделать, мы должны сначала преобразовать множество (обратно) в list.

Код

my_list = list(my_set)
my_list[0]
Результат:
1



Множества часто могут быть полезны на практике, например, для поиска уникальных идентификаторов. Предположим, у нас есть список покупок и мы хотим быстро узнать, сколько уникальных товаров было приобретено.
Предположим, у нас есть ID продуктов, которые были куплены в переменной transactions.

Код

transactions = [1, 1, 2, 1, 2, 3, 5, 6, 7, 1, 8]
Если мы хотим найти уникальное количество товаров, нужно просто составить множество из следующего списка и узнать его длину:

Код

set_transactions = set(transactions)
set_transactions
Результат:
{1, 2, 3, 5, 6, 7, 8}

Код

len(set_transactions)
Результат:
7

Как видим, у нас есть 7 уникальных товаров.

Еще одним полезным свойством множеств, которое я очень часто использую - являются операции над множествами:
  • A.union(B) Объединение множеств
  • объединение всех элементов из обоих наборов A и B
  • A.intersection(B) Пересечение множеств
  • включение элементов общих для обоих наборов А и В
  • A.difference(B) Разница между множествами
  • содержит только элементы которые есть в множестве A, но не в множестве B
  • A.symmetric_difference(B) Симметричная разница
  • содержит все элементы из обоих множеств, кроме общей части А и В


Код

set_a = {1, 2, 3, 4, 5}
set_b = {4, 5, 6, 7}
Объединение "A" и "B"
set_a | set_b
Код

set_a_or_b = set_a | set_b
set_a_or_b
Результат:
{1, 2, 3, 4, 5, 6, 7}


Пересечение "A" и "B"
set_a & set_b

Код

set_a_intersect_b = set_a & set_b
set_a_intersect_b
Результат:
{4, 5}

Разница кроме общей части с "B"
set_a - set_b


Код

set_a_diff_b = set_a - set_b
set_a_diff_b
Результат:
{1, 2, 3}

"A" и "B" кроме общей части
set_a ^ set_b
Код

set_a_sym_b = set_a ^ set_b
set_a_sym_b
Результат:
{1, 2, 3, 6, 7}


Tuple
Кортеж - также полезная структура данных.
Кстати в данном случае скобки круглые :).

Код

my_tuple = (0, 7, 2)

print(my_tuple)
type(my_tuple)
Результат:
(0, 7, 2)
tuple
tuple работает очень похоже на list, но имеет ряд отличий. Но начнем с общего. Доступ к данным аналогичен. Используя индекс, мы можем перейти к отдельным значениям. Например, чтобы перейти ко второму элементу, мы используем индекс 1.

Код

my_tuple[1]
Результат:
7
Какие отличия?
list заключен в квадратные скобки [], a tuple в круглые (). Как вариант для кортежа, скобки можно опустить, но тогда должно быть как минимум два элемента (запятая должна появиться хотя бы один раз).
Проверяем.
Код

my_tuple = 0, 1, 2 
print(my_tuple)
Результат:
(0, 1, 2)
Второе, tuple это неизменяемый тип (англ. immutable type). На практике это означает, что как только создал кортеж, то все - уже не сможешь его перезаписать.
Код

my_tuple[1] = 1
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-40-6c299328a8a7> in <module>
----> 1 my_tuple[1] = 1

TypeError: 'tuple' object does not support item assignment

Видишь появилось исключение - TypeError: 'tuple' object does not support item assignment.
Оно ругается, что нельзя перезаписать (изменить значения) tuple. Возможно, это для новичка покажется очень странным, правда? Но поверь, то, что данные нельзя перезаписать, - это очень классная штука, особенно когда мы работаем в многопоточной системе.

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

[1].__sizeof__(), (1).__sizeof__()
Результат:
(48, 28)

А напоследок, в защиту списка, стоит отметить, что он содержит гораздо больше дополнительных функций.

Полезно знать!
Кстати, используя __dict__ можно подсмотреть, какие методы доступны. Смотри как легко можно сравнить, что можно делать с list и tuple.

Код

list.__dict__
Результат:
mappingproxy({'__repr__': <slot wrapper '__repr__' of 'list' objects>,
'__hash__': None,
'__getattribute__': <slot wrapper '__getattribute__' of 'list' objects>,
'__lt__': <slot wrapper '__lt__' of 'list' objects>,
'__le__': <slot wrapper '__le__' of 'list' objects>,
'__eq__': <slot wrapper '__eq__' of 'list' objects>,
'__ne__': <slot wrapper '__ne__' of 'list' objects>,
'__gt__': <slot wrapper '__gt__' of 'list' objects>,
'__ge__': <slot wrapper '__ge__' of 'list' objects>,
'__iter__': <slot wrapper '__iter__' of 'list' objects>,
'__init__': <slot wrapper '__init__' of 'list' objects>,
'__len__': <slot wrapper '__len__' of 'list' objects>,
'__getitem__': <method '__getitem__' of 'list' objects>,
'__setitem__': <slot wrapper '__setitem__' of 'list' objects>,
'__delitem__': <slot wrapper '__delitem__' of 'list' objects>,
'__add__': <slot wrapper '__add__' of 'list' objects>,
'__mul__': <slot wrapper '__mul__' of 'list' objects>,
'__rmul__': <slot wrapper '__rmul__' of 'list' objects>,
'__contains__': <slot wrapper '__contains__' of 'list' objects>,
'__iadd__': <slot wrapper '__iadd__' of 'list' objects>,
'__imul__': <slot wrapper '__imul__' of 'list' objects>,
'__new__': <function list.__new__(*args, **kwargs)>,
'__reversed__': <method '__reversed__' of 'list' objects>,
'__sizeof__': <method '__sizeof__' of 'list' objects>,
'clear': <method 'clear' of 'list' objects>,
'copy': <method 'copy' of 'list' objects>,
'append': <method 'append' of 'list' objects>,
'insert': <method 'insert' of 'list' objects>,
'extend': <method 'extend' of 'list' objects>,
'pop': <method 'pop' of 'list' objects>,
'remove': <method 'remove' of 'list' objects>,
'index': <method 'index' of 'list' objects>,
'count': <method 'count' of 'list' objects>,
'reverse': <method 'reverse' of 'list' objects>,
'sort': <method 'sort' of 'list' objects>,
'__doc__': 'Built-in mutable sequence.\n\nIf no argument is given, the constructor creates a new empty list.\nThe argument must be an iterable if specified.'})


Код

tuple.__dict__
Результат:
mappingproxy({'__repr__': <slot wrapper '__repr__' of 'tuple' objects>,
'__hash__': <slot wrapper '__hash__' of 'tuple' objects>,
'__getattribute__': <slot wrapper '__getattribute__' of 'tuple' objects>,
'__lt__': <slot wrapper '__lt__' of 'tuple' objects>,
'__le__': <slot wrapper '__le__' of 'tuple' objects>,
'__eq__': <slot wrapper '__eq__' of 'tuple' objects>,
'__ne__': <slot wrapper '__ne__' of 'tuple' objects>,
'__gt__': <slot wrapper '__gt__' of 'tuple' objects>,
'__ge__': <slot wrapper '__ge__' of 'tuple' objects>,
'__iter__': <slot wrapper '__iter__' of 'tuple' objects>,
'__len__': <slot wrapper '__len__' of 'tuple' objects>,
'__getitem__': <slot wrapper '__getitem__' of 'tuple' objects>,
'__add__': <slot wrapper '__add__' of 'tuple' objects>,
'__mul__': <slot wrapper '__mul__' of 'tuple' objects>,
'__rmul__': <slot wrapper '__rmul__' of 'tuple' objects>,
'__contains__': <slot wrapper '__contains__' of 'tuple' objects>,
'__new__': <function tuple.__new__(*args, **kwargs)>,
'__getnewargs__': <method '__getnewargs__' of 'tuple' objects>,
'index': <method 'index' of 'tuple' objects>,
'count': <method 'count' of 'tuple' objects>,
'__doc__': "Built-in immutable sequence.\n\nIf no argument is given, the constructor returns an empty tuple.\nIf iterable is specified the tuple is initialized from iterable's items.\n\nIf the argument is a tuple, the return value is the same object."})


А давай сразу закрепим знания с наборами. Найдем такие функции, которые есть и в списке и кортеже.

Код

 set(list.__dict__) & set(tuple.__dict__)
Результат:
{'__add__',
'__contains__',
'__doc__',
'__eq__',
'__ge__',
'__getattribute__',
'__getitem__',
'__gt__',
'__hash__',
'__iter__',
'__le__',
'__len__',
'__lt__',
'__mul__',
'__ne__',
'__new__',
'__repr__',
'__rmul__',
'count',
'index'}

Теперь можно посмотреть, что есть в tuple, но чего нет в list.

Код

set(tuple.__dict__) -  set(list.__dict__)
Результат:
{'__getnewargs__'}
А теперь проверим наоборот.

Код

set(list.__dict__) - set(tuple.__dict__)
Результат:
{'__delitem__',
'__iadd__',
'__imul__',
'__init__',
'__reversed__',
'__setitem__',
'__sizeof__',
'append',
'clear',
'copy',
'extend',
'insert',
'pop',
'remove',
'reverse',
'sort'}
Так, как и писал, в списке больше встроенных функций. Часть из них - это изменения списка (например, добавить или удалить элемент), но также, например, есть сортировка (или обратная сортировка).

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

my_name = 'Иван'
print(my_name)
type(my_name)
Результат:
Иван
str
string - в некотором роде можно рассматривать, как список символов (букв). Следовательно, как и в случае с list, на эти элементы можно ссылаться с помощью индексов. Итак, чтобы перейти к первой букве, мы используем индекс 0, а к последней букве -1 и т. д.
Код

my_name[0]
Результат:
'И'

Код

my_name[-1] # Ты получишь тот же результат my_name[len(my_name) - 1]
Результат:
'н'
Точно так же можешь получить фрагмент string (т.е. substring). Кстати, это Твое следующее задание :)

Задание 1.2.4
my_name на данный момент он содержит имя Иван. Твоя задача - скачать только часть текста. Ожидаемый ответ: ван.

Помни, что string тоже immutable (как и tuple), поэтому не можешь изменить букву. Смотри.

Код

my_name[0] = 'A'
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-50-2671cbeca83c> in <module>
----> 1 my_name[0] = 'A'

TypeError: 'str' object does not support item assignment


Появилась ошибка TypeError: 'str' object does not support item assignment.
Тот же самый механизм как и при перезаписывании значений в tuple.
Также обрати внимание на кавычки вокруг слова. Есть два варианта:
  • одиночный, иногда называемый апострофом, например, 'какой-то текст'
  • двойной, например, "какой-то текст"
Какую форму использовать? Это решать Тебе. Однако для единообразия стоит придерживаться одной формы в рамках данного кода. Хотя часто советую именно использовать двойные кавычки по умолчанию.

Динамические списки
Предположим, Ты хочешь объединить фрагменты информации в одну string. Это можно сделать несколькими способами. Взгляни на пример ниже.


Код

 "Итого: " + str(100) + "руб. (" + str(7) + " шт.)"
Результат:
'Итого: 100руб. (7 шт.)'

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

Код

"Итого: {0}руб. ({1} шт.)".format(100, 7)
Результат:
'Итого: 100руб. (7 шт.)'


Индекс аргумента указывается в фигурных скобках, например, {0}, что означает нулевой индекс, то есть первый элемент .format (100, 7). В нашем случае это будет 100. В новых версиях Python есть и другие способы, но нужно быть осторожным с этим, потому что последняя версия Python есть не везде. Например, можно использовать f-string (доступно от Python 3.6 - вышло в мир 01 августа 2015).

f-string
Предположим, что у нас есть две переменные
amount=100
unit=7
И мы хотим их значения показать в динамической строке. Это можно сделать так (обрати внимание, что в строке переменные были обозначены вот так {amount} и {unit}).


Код

amount=100
unit=7
f"Итого: {amount}руб. ({unit} шт.)"
Результат:
'Итого: 100руб. (7 шт.)'


Dict
Словарь - очередная структура данных, которая очень полезна в реальной жизни (и одна из моих любимых).
Говоря о группе и ее рейтингах, иногда также стоит знать, у кого какой рейтинг, а не просто иметь анонимную строку чисел. На помощь приходит словарь (dict). Это структура, состоящая из пары ключей и значений. В этом случае ключом может быть имя, а значением - оценка. Посмотри, как это выглядит в коде.

Код

dict_scores = {
    'Иван': 4,
    'Маша': 5,
    'Игорь': 5,
    'Руслан': 3,
    'Наташа': 4
}

print(dict_scores)
type(dict_scores)
Результат:
{'Иван': 4, 'Маша': 5, 'Игорь': 5, 'Руслан': 3, 'Наташа': 4}
dict
Чтобы узнать, какой рейтинг, например, у Ивана, достаточно сослаться на ссылку ниже.

Код

dict_scores['Иван']
Результат:
4


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

Код

dict_scores['Ярик']
Результат:
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-56-82b7707fe6d5> in <module>
----> 1 dict_scores['Ярик']

KeyError: 'Ярик'

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

if 'Иван' in dict_scores:
    print('Иван есть в словаре')
    
if 'Ярик' in dict_scores:
    print('Ярик есть в словаре')
Результат:
Иван есть в словаре



Мы можем расширить условие, добавив else.

Код

if 'Ярик' in dict_scores:
    print('Ярик есть в словаре')
else:
    print('Ярика нет в словаре')
Результат:
Ярика нет в словаре
Обрати внимание
  1. В конце условной строки стоит двоеточие if ... :
  2. В условном блоке есть отступы. Помни. Интервал в Python очень важен.
  3. По умолчанию предполагается, что количество пробелов в отступе равно четырем (или одному tab).
  4. Иногда обсуждают, что лучше - пробел или табуляция (однако я рекомендую использовать пробелы).
  5. Одно можно сказать наверняка в этом обсуждении - избегай смешивания пробелов с табуляциями (да, так тоже иногда делают)
  6. Интеллектуальная IDE позволяет Тебе преобразовывать tab в пробелы (то есть Ты нажимаешь tab и получаешь 4 пробела. Магия! :))
  7. Python не имеет фигурных скобок, что характерно для других языков. Если мы хотим отметить начало и конец блока, мы используем пробелы. Следовательно, Ты должен быть очень точным в интервалах (каждый блок должен быть последовательным). Я упоминал, что интервал важен? :)

Ты можешь еще больше добавить условий (добавив, например, elif, что является сокращением от else if). Люди, которые программируют на C / C ++ / Java, могут потеряться без точки с запятой :). Расслабься, Ты к этому привыкнешь.
Повторим "скобки"
Я знаю, что поначалу это может быть сложнее, так что присмотрись :).
  • круглые скобки (...) например, для вызова функции print('Hello world!') или tuple(1, 2, 3)
  • квадратные скобки [...] например, для списков [1, 2, 3] или доступа к отдельным элементам в list или tuple: my_list [0] или my_tuple [0]
  • фигурные скобки {...} например, для словарей {'key': 'value'} или множества {1, 2, 3}

Python это язык динамически типизированный
На практике это означает, что Тебе не нужно явно указывать тип переменной, интерпретатор сам догадывается. Классная вещь! Однако, как это обычно бывает в жизни, у такого решения есть свои достоинства и недостатки. Преимущество в том, что код на Python выглядит элегантно, и с несколькими символами в строке можно многого добиться. К недостаткам определенно стоит отнести более медленное время работы (потому что, если мы не укажем тип переменной, интерпретатор должен будет делать всю работу за нас). К счастью, есть решения для устранения этих недостатков (включая библиотеку numpy / pandas). Ты узнаешь о них в следующем модуле.

1.2.5 Случайная задача на закрепление материала
Сколько же уникальных оценок содержится в списке group_scores?

Что делать если возникли трудности?
  1. Все необходимое для решения задач есть в ноутбуке. Возможно, стоит пробежаться по материалу еще раз.
  2. Если все же задача не поддается, посмотри, что про нее пишут в чате - скорее всего сложности возникли не только у Тебя - это нормально.
  3. В каждой задаче есть скрытая подсказка и уже в крайнем случае - ответ (сюда заглядывай только если в течение 15 минут не получается никак решить задание.
Это был пример урока из первого модуля курса "Практическое введение в Python для Data Science". Всего в курсе 15 уроков + бонусные задания, 15 пошаговых видео для каждого урока с подробными объяснениями.
Мы предоставляем готовое окружение, где изучаешь материал с помощью текста и видео. Ничего устанавливать и настраивать не нужно.

Получаешь практику, пишешь код уже на первых уроках! Обучайся в своем ритме - доступ к курсу будет открыт 24/7.
Присоединяйся сейчас и начни свое комфортное обучение.