Полное руководство по Python для начинающих в 2023 году
5 апреля 2023 г.Python — это невероятно мощный язык программирования, который используется миллионами разработчиков в производственных системах по всему миру. Он прост в освоении, бесплатен в использовании и имеет огромное сообщество разработчиков, которые всегда готовы помочь.
Если вы интересуетесь внутренней веб-разработкой, наукой о данных, инженер данных или просто хотите автоматизировать некоторые из ваших скучных задач, Python — отличное место для начала.< /p>
Вы бы предпочли учиться на практике?
Я включил в это руководство все статические материалы только для чтения, которые вам понадобятся, но если вы хотите больше практических занятий, вы можете воспользоваться интерактивной версией этого руководства. конечно, вместе с задачами и проектами по программированию на Boot.dev здесь.
Глава 1. Введение
Тысячи студентов начинают свой путь программирования прямо здесь, с Python. Мы считаем, что это лучший язык программирования для начала. Python известен как простой язык, который легко читать и писать.
Однако то, что это просто, не означает, что это бесполезно! Python — это чрезвычайно популярный язык в отрасли, который хорошо известен благодаря:
* Бэкэнд веб-серверы * DevOps и облачная инженерия * Машинное обучение * Скрипты и автоматизация * и т.д...
С другой стороны, он не особенно известен интерфейсной работой. Хотя это возможно, Python обычно не используется для создания визуальных пользовательских интерфейсов.
Настройка локальной среды разработки
Чтобы начать работу с Python, вам необходимо установить команду python
на свой компьютер, а затем установить текстовый редактор или IDE. Если вы еще не знакомы с тем, как это сделать, у меня есть полное пошаговое руководство по проекту. здесь вы можете подписаться.
Если вы можете редактировать и запускать код Python на своем компьютере, вы готовы продолжить!
Что такое «Код»?
Код — это просто набор инструкций, которым может следовать компьютер. Компьютеры подчиняются каждой инструкции, одной за другой.
Программы могут состоять из множества инструкций. Как и многие. Как и миллионы.
Сложение — одна из самых распространенных инструкций в программировании.
Печать чисел
print()
может печатать текст с использованием кавычек:
print("some text here")
но он также может печатать числа без кавычек:
print(1)
и вы можете выполнять математические операции прямо внутри круглых скобок:
print(1 + 2)
Попробуйте некоторые из этих фрагментов кода в своем редакторе! Например, вы можете создать файл с именем hello.py
и написать следующий код:
print("Hello, world!")
print(1 + 2)
Затем запустите файл с помощью python hello.py
и посмотрите, что произойдет.
Несколько инструкций
Код выполняется по порядку, начиная с верхней части программы. Например:
print("this prints first")
print("this prints second")
print("this prints last")
Синтаксические ошибки
Синтаксис — это жаргон, обозначающий "правильный код, понятный компьютеру". Например,
prnt("hello world")
недействителен синтаксис, поскольку prnt()
не является допустимой функцией, "печать" написано неправильно. В результате будет выдана ошибка, и код не будет выполняться.
Синтаксис зависит от языка
Синтаксис языка кодирования составляет правила, определяющие, как должным образом структурированные выражения и операторы выглядят в этом языке. Например, в Python следующий синтаксис будет считаться правильным:
print("hello world")
На другом языке программирования, таком как Go, правильный синтаксис будет таким:
fmt.Println("hello world")
В коде может быть много разных проблем, которые мешают ему работать должным образом. Вот некоторые примеры:
- Ошибка в логике. Например, программа, которая должна складывать числа, вместо этого умножает их
- Проблема со скоростью. Программа, которая вычисляет, как вести идеальную партию в шахматы, может никогда не закончиться, потому что требует слишком много вычислений.
- Проблема с синтаксисом. Это самая распространенная проблема для новых разработчиков. К счастью, интерпретатор Python попытается выдать описательное сообщение об ошибке в консоли, чтобы помочь вам найти проблему.
Глава 2. Переменные
Переменные — это способ хранения данных в нашей программе. До сих пор мы напрямую печатали данные, передавая их непосредственно в функцию print()
.
Теперь мы собираемся научиться сохранять данные в переменных, чтобы мы могли использовать и изменять их, прежде чем нам нужно будет их распечатать.
Переменная — это определяемое нами имя, которое будет указывать на некоторые данные. Например, я мог бы определить новую переменную с именем my_height
и присвоить ей значение 100. Я также мог бы определить переменную с именем my_name
и присвоить ей значение «Lane».< /p>
Создание переменных
Чтобы создать новую переменную в Python, мы используем следующий синтаксис:
my_new_variable_two = 2
this_can_be_called_anything = 3
Переменные различаются
Переменные называются "переменными", потому что они могут содержать любое значение, и это значение может меняться (оно меняется).
Например, следующее напечатает 20
:
acceleration = 10
acceleration = 20
print(acceleration)
Строка acceleration = 20
переназначает значение acceleration
на 20. Она перезаписывает все, что удерживалось в переменной acceleration
раньше.
Давайте посчитаем
Теперь, когда мы знаем, как сохранять и изменять значения переменных, давайте посчитаем!
Вот несколько примеров распространенных математических операторов в синтаксисе Python.
sum = a + b
difference = a - b
product = a * b
quotient = a / b
Комментарии
Комментарии не работают как код, они игнорируются компьютером. Комментарии полезны для добавления напоминаний или объяснения того, что делает фрагмент кода на простом английском языке.
Однострочный комментарий
# speed is a variable describing how fast your player moves
speed = 2
Многострочные комментарии (строки документации)
Вы также можете использовать тройные кавычки для начала и окончания многострочных комментариев:
"""
the code found below
will print 'Hello, World!' to the console
"""
print('Hello, World!')
Это полезно, если вы не хотите добавлять #
в начало каждой строки при написании абзацев комментариев.
Имена переменных
Имена переменных не могут содержать пробелов, они представляют собой непрерывные строки символов.
В Python вы должны использовать "snake_case" при создании имен переменных - это стало "правилом большой палец» для языка. Для сравнения, в «верблюжьем регистре» начало каждого нового слова, кроме первого, пишется с большой буквы.
Без корпуса (чистое безумие)
somevariablehere = 10
Чехол для верблюда
someVariableHere = 10
Змеиный кейс
some_variable_here = 10
Основные типы переменных
В Python существует несколько основных типов данных.
Тип строки
«Строки» — это необработанный текст в языке кодирования. Их называют «строками», потому что они представляют собой список символов, соединенных вместе. Строки объявляются в Python с использованием одинарных или двойных кавычек. Тем не менее, для согласованности мы предпочитаем двойные кавычки.
name_with_single_quotes = 'boot.dev'
name_with_double_quotes = "boot.dev"
Числовые типы
Числа не заключаются в кавычки при создании, но могут содержать десятичные дроби и отрицательные знаки.
Целые числа – это числа без десятичных знаков
.x = 5
y = -5
"Плавающая" — это число с десятичным знаком
x = 5.2
y = -5.2
Булев тип
"Boolean" (или "bool") — это тип, который может иметь только одно из двух значений: True
или False
. Как вы, возможно, слышали, компьютеры действительно используют только 1 и 0. Эти 1 и 0 являются просто значениями Boolean
.
0 = False
1 = True
is_tall = True
Переменные NoneType
Не все переменные имеют значение. Мы можем объявить «пустую» переменную, установив для нее значение None
.
empty = None
Значение empty
в этом случае равно None
, пока мы не используем оператор присваивания =
, чтобы присвоить ему значение. р>
None НЕ является конкретной строкой
Обратите внимание, что тип None
не совпадает со строкой со значением "None":
my_none = None # this is a None-type
my_none = "None" # this is a string
Динамическая типизация
Python динамически типизируется. Все это означает, что переменная может хранить любой тип, и этот тип может изменяться.
Например, если я создаю числовую переменную, я могу позже изменить эту переменную на строку:
Это действительно:
speed = 5
speed = "five"
То, что вы можете, не означает, что вы должны!
Практически во всех случаях плохая идея изменять тип переменной. "Правильно" сделать, это просто создать новый. Например:
speed = 5
speed_description = "five"
Что, если бы он не был динамически типизирован?
Статически типизированные языки, такие как Go (который вы изучите в следующих курсах), имеют статический, а не динамический тип. В статически типизированном языке, если вы попытаетесь присвоить значение переменной неправильного типа, произойдет сбой программы.
Если бы Python имел статическую типизацию, первый из предыдущих примеров вылетел бы на второй строке, speed = "five"
. Компьютер выдаст ошибку типа вы не можете присвоить строковое значение ("пять") числовой переменной (скорость)
https://www.youtube.com/watch?v=GqXpFycPWLE&embedable=true а>
Математика со строками
Большинство математических операторов, которые мы рассматривали ранее, не работают со строками, за исключением оператора сложения +
. При работе со строками оператор +
выполняет «конкатенацию».
"Конкатенация" – красивое слово, означающее объединение двух строк.
first_name = "Lane "
last_name = "Wagner"
full_name = first_name + last_name
full_name
теперь содержит значение «Лейн Вагнер».
Обратите внимание на дополнительный пробел в конце "Lane"
в переменной first_name
. Это дополнительное пространство предназначено для разделения слов в конечном результате: "Лейн Вагнер"
.
Объявление нескольких переменных
Мы можем сэкономить место при создании множества новых переменных, объявив их в одной строке:
sword_name, sword_damage, sword_length = "Excalibur", 10, 200
Это то же самое, что:
sword_name = "Excalibur"
sword_damage = 10
sword_length = 200
В одной строке может быть объявлено любое количество переменных, а переменные, объявленные в одной строке, должны быть каким-то образом связаны друг с другом, чтобы код оставался понятным.
Мы называем код, который легко понять, "чистым кодом".
Глава 2. Основы вычислений
Числа Python
В Python числа без десятичной части называются целыми
— так же, как и в математике.
Целые числа — это просто целые числа, положительные или отрицательные. Например, 3
и -3
являются примерами целых чисел.
Арифметика может быть выполнена так, как вы могли ожидать:
Дополнение
2 + 1
# 3
Вычитание
2 - 1
# 1
Умножение
2 * 2
# 4
Отдел
3 / 2
# 1.5 (a float)
Это на самом деле немного отличается - деление на два целых числа на самом деле даст float
. Как вы уже догадались, число с плавающей запятой позволяет использовать десятичные значения.
Целые числа
В Python числа без десятичной части называются целыми
. Сравните это с JavaScript, где все числа имеют тип Number
.
Целые числа — это просто целые числа, положительные или отрицательные. Например, 3
и -3
являются примерами целых чисел.
Поплавки
Как вы уже догадались, число с плавающей запятой – это числовой тип, допускающий десятичные значения.
my_int = 5
my_float = 5.5
Разделение этажей
Python имеет отличную встроенную поддержку математических операций. Это, помимо прочего, объясняет, почему он добился такого успеха в приложениях искусственного интеллекта, машинного обучения и обработки данных.
Деление пола похоже на обычное деление, за исключением того, что после этого в результате получается пол, что означает, что остаток удаляется . Как и следовало ожидать, это означает, что результатом является целое число
, а не число с плавающей запятой
.
7 // 3
# 2 (an integer)
https://www.youtube.com/watch?v=fmM07zqoT5c&embedable=true а>
Экспоненты
Python имеет встроенную поддержку экспонент, для чего большинству языков требуется библиотека math
.
# reads as "three squared" or
# "three raised to the second power"
3 ** 2
# 9
https://www.youtube.com/watch?v=sP8yhvtvipo&embedable=true а>
Изменение на месте
Довольно часто возникает необходимость изменить значение переменной на основе ее текущего значения.
player_score = 4
player_score = player_score + 1
# player_score now equals 5
player_score = 4
player_score = player_score - 1
# player_score now equals 3
Пусть вас не смущает тот факт, что выражение player_score = player_score - 1
не является допустимым математическим выражением. Не имеет значения, это допустимый код. Это допустимо, потому что выражение следует читать на английском языке следующим образом:
Присвоить player_score старое значение player_score минус 1
Плюс равно
Python упрощает переназначение при выполнении математических операций. В JavaScript или Go вы можете быть знакомы с синтаксисом ++
для увеличения числовой переменной. В Python вместо этого используется оператор +=
.
star_rating = 4
star_rating += 1
# star_rating is now 5
Научная нотация
Как мы уже говорили ранее, с плавающей запятой
– это положительное или отрицательное число, с дробной частью.
Вы можете добавить букву e
или E
, за которой следует положительное или отрицательное целое число, чтобы указать, что вы используете научная запись.
print(16e3)
# Prints 16000.0
print(7.1e-2)
# Prints 0.071
Если вы не знакомы с экспоненциальной записью, это способ выражения чисел, которые слишком велики или слишком малы для обычного написания.
Вкратце, число, следующее за e
, указывает, на сколько разрядов следует переместить десятичную дробь вправо для положительного числа или влево для отрицательного числа.
Подчеркивание для удобства чтения
Python также позволяет представлять большие числа в десятичном формате, используя знаки подчеркивания вместо запятых, чтобы их было легче читать.
num = 16_000
print(num)
# Prints 16000
num = 16_000_000
print(num)
# Prints 16000000
Логические операторы
Вы, вероятно, знакомы с логическими операторами И
и ИЛИ
.
Логические операторы работают с логическими значениями, True
и False
.< /p>
Логический оператор И
требует, чтобы оба входных данных были True
для возврата True
. Логический оператор ИЛИ
требует, чтобы по крайней мере один ввод был True
, чтобы вернуть True
.
Например:
True AND True = True
True AND False = False
False AND False = False
True OR True = True
True OR False = True
False OR False = False
Синтаксис Python
print(True and True)
# prints True
print(True or False)
# prints True
Вложение в круглые скобки
Мы можем вкладывать логические выражения с помощью круглых скобок.
print((True or False) and False)
Сначала мы оцениваем выражение в скобках (True или False)
. Он оценивается как True
:
print(True and False)
True and False
оценивается как False
:
print(False)
Итак, print((True или False) и False)
выводит на консоль "False".
Двоичные числа
Двоичные числа — это просто числа с основанием 2. Они работают так же, как «обычные» числа с основанием 10, но с 2 символами вместо 10.
Каждый 1
в двоичном числе представляет большее кратное 2. В четырехзначном числе это означает, что у вас есть место для восьмерки, места для четверки, места для двойки и места для единицы. Подобно тому, как в десятичной дроби у вас будут тысячные, сотые, десятки и единицы.
* <код>0001код> = 1
* <код>0010код> = 2
* <код>0011код> = 3
* <код>0100код> = 4
* <код>0101код> = 5
* <код>0110код> = 6
* <код>0111код> = 7
* 1000
= 8
https://www.youtube.com/watch?v=M3VLyEDPDR8&embedable=true а>
Побитовое "&" Оператор
Побитовые операторы похожи на логические операторы, но вместо операций с логическими значениями они применяют ту же логику ко всем битам в значении. Например, предположим, что числа 5
и 7
представлены в двоичном формате а>. Вы можете выполнить побитовую операцию И
, и результатом будет 5
.
0101 = 5
&
0111 = 7
=
0101 = 5
1
в двоичном формате соответствует True
, а 0
соответствует False
. Так что на самом деле побитовая операция — это просто набор логических операций, которые выполняются в тандеме.
&
— это побитовый оператор AND
в Python. 5 & 7 = 5
, а 5 & 2 = 0код>.
0101 = 5
&
0010 = 2
=
0000 = 0
Двоичная запись
При записи числа в двоичном формате префикс 0b
используется для обозначения того, что последующее является двоичным числом.
0b0101
равно 50b0111
равно 7
Пример: разрешения гильдии
В бэкэнд-разработке принято хранить разрешения пользователей в виде двоичных значений. Подумайте об этом, если у меня есть 4
различные разрешения, которые может иметь пользователь, то я могу сохранить это как 4-значное двоичное число, и если присутствует определенный бит, я знаю, что разрешение включено.
Предположим, что у нас есть 4 разрешения:
can_create_guild
– Крайний левый битcan_review_guild
– второй бит слеваcan_delete_guild
— второй бит справаcan_edit_guild
– крайний правый бит
Которые представлены 0b0000
. Например, если у пользователя есть только разрешение can_create_guild
, его двоичные разрешения будут 0b1000
. Пользователь с can_review_guild
и can_edit_guild
будет 0b0101
.
Чтобы проверить, скажем, разрешение can_review_guild
, мы можем выполнить побитовую операцию И
над разрешениями пользователя и включенным битом can_review_guild
(0b0100код>). Если результат снова
0b0100
, мы знаем, что у них есть конкретное разрешение!
Побитовое "|" Оператор
Как вы могли догадаться, побитовый оператор "или" похож на побитовый оператор "и" тем, что работает с двоичными, а не с логическими значениями. Однако побитовый оператор «или» объединяет биты «ИЛИ». Вот пример:
* 0101
равно 5
* 0111
равен 7
0101
|
0111
=
0111
1
в двоичном формате соответствует True
, а 0
соответствует False
. Таким образом, побитовая операция — это просто набор логических операций, которые выполняются в тандеме. Когда два двоичных числа объединяются по ИЛИ, результат имеет 1
в любом месте, где любое из входных чисел имеет 1
в этом месте.
|
— это побитовый оператор OR
в Python. <код>5 | 7 = 7 и 5 | 2 = 7
тоже!
0101 = 5
|
0010 = 2
=
0111 = 7
Нет
Мы пропустили очень важный логический оператор - not
. Оператор not
обращает результат. Он возвращает False
, если ввод был True
, и наоборот.
print(not True)
# Prints: False
print(not False)
# Prints: True
Глава 3. Сравнение
Операторы сравнения
При кодировании необходимо иметь возможность сравнивать два значения. Булева логика
— это название таких операций сравнения, которые всегда приводят к True
или False
.
Операторы:
<
"меньше чем">
"больше чем"<=
"меньше или равно">=
"больше или равно"==
"равно"!=
"не равно"
Например:
5 < 6 # evaluates to True
5 > 6 # evaluates to False
5 >= 6 # evaluates to False
5 <= 6 # evaluates to True
5 == 6 # evaluates to False
5 != 6 # evaluates to True
https://www.youtube.com/watch?v=QZdCkBWsC-4&embedable =правда
Оценки
Когда происходит сравнение, результатом сравнения является просто логическое значение, это либо True
, либо False
.
Возьмите следующие два примера:
is_bigger = 5 > 4
is_bigger = True
В обоих приведенных выше случаях мы создаем переменную Boolean
с именем is_bigger
со значением True
.
Поскольку 5 > 4
, is_bigger
всегда присваивается значение True
.
Зачем мне использовать сравнение, если я могу просто установить для него значение «Истина»?
В этом случае вы бы этого не сделали. Однако давайте представим, что вместо жестко закодированных чисел 5
и 4
у нас есть некоторые динамические переменные, значения которых нам неизвестны. из. Например, вы создаете видеоигру и вам нужно отслеживать очки игроков.
Чтобы подсчитать, кто победит, вам нужно будет написать что-то вроде:
# player_one_points and player_two_points are defined and change somewhere else in the game's code
player_one_wins = player_one_points > player_two_points
print(player_one_wins)
# prints "True" when player one is winning, otherwise prints "False"
Увеличение/уменьшение
Если мы изменяем число и просто хотим увеличить (прибавить) или уменьшить (вычесть), для этого есть специальные операторы.
shield_armor = 4
shield_armor += 1
# shield_armor now equals 5
shield_armor += 2
# shield_armor now equals 7
shield_armor = 4
shield_armor -= 1
# shield_armor now equals 3
shield_armor -= 2
# shield_armor now equals 1
Обратите внимание, что shield_armor+=1
— это просто сокращение от shield_armor = Shield_armor + 1
Инструкции if
Часто полезно выполнять код только при выполнении определенного условия:
if CONDITION:
# do some stuff here
например:
if bob_score > bill_score:
print("Bob Wins!")
Если-иначе
За оператором if
может следовать ноль или более операторов elif
(что означает "else if"), за которыми может следовать ноль или один оператор else
. Например:
if score > high_Score:
print('High score beat!')
elif score > second_highest_score:
print('You got second place!')
elif score > third_highest_score:
print('You got third place!')
else:
print('Better luck next time')
Сначала оценивается оператор if
. Если оно равно True
, выполняется тело оператора if, а все остальные операторы else
игнорируются.
Если первый if
ложный, оценивается следующий elif
. Аналогичным образом, если True
, выполняется его тело, а остальные игнорируются.
Если ни один из операторов if
не оценивается как True
, то последний оператор else
будет единственным выполненным телом.
Правила «если-иначе»
- У вас не может быть
elif
илиelse
безif
- Вы можете использовать
else
безelif
Глава 5. Циклы
Циклы — лучший друг программиста. Циклы позволяют выполнять одну и ту же операцию несколько раз без необходимости каждый раз писать ее явно.
Например, давайте представим, что я хочу напечатать числа от 0 до 9.
Я мог бы сделать это:
print(0)
print(1)
print(2)
print(3)
print(4)
print(5)
print(6)
print(7)
print(8)
print(9)
Несмотря на это, использование цикла сэкономило бы мне много времени на набор текста. Особенно, если я хотел сделать одно и то же тысячу или миллион раз.
"цикл for" в Python записывается так:
for i in range(0, 10):
print(i)
На английском языке код гласит:
- Начните с
i
равно0
. (i в диапазоне (0
) - Если
i
не меньше 10 (range(0, 10)
), выйти из цикла. - Выведите
i
на консоль. (печать(i)
) - Добавьте
1
вi
. (range
по умолчанию увеличивается на 1) - Вернитесь к шагу
2
В результате числа 0–9
записываются в консоль по порядку.
Пробелы важны в Python!
Тело цикла for должно иметь отступ, иначе вы получите синтаксическую ошибку.
Пример
Этот код выводит числа от 0 до 9 на консоль.
for i in range(0, 10):
print(i)
Продолжение диапазона
Функция range()
, которую мы использовали в циклах for
, на самом деле имеет необязательный третий параметр: "шаг".
for i in range(0, 10, 2):
print(i)
# prints:
# 0
# 2
# 4
# 6
# 8
Параметр "шаг" определяет, на сколько увеличивается i
при каждой итерации цикла. Вы даже можете вернуться назад:
for i in range(3, 0, -1):
print(i)
# prints:
# 3
# 2
# 1
F-строки в Python
Вы можете создать строку с динамическими значениями, используя f-строки
в Python. Это прекрасный синтаксис, и я бы хотел, чтобы использовалось больше языков программирования.
num_bananas = 10
print(f"You have {num_bananas} bananas")
# You have 10 bananas
Открывающие кавычки должны начинаться с f
, после чего значения любых переменных в фигурных скобках будут интерполированы в строку.
Глава 6. Списки
Естественным способом организации и хранения данных является использование списка
. Некоторые языки называют их «массивами», но в Python мы называем их просто списками. Подумайте обо всех приложениях, которые вы используете, и о том, сколько элементов в приложении организовано в списки.
Например:
- Фид Твиттера – это список сообщений
- Интернет-магазин – это список товаров.
- Состояние шахматной партии – это список ходов.
- Этот список представляет собой список вещей, которые являются списками
Списки в Python объявляются с помощью квадратных скобок с запятыми, разделяющими каждый элемент:
inventory = ["Iron Breastplate", "Healing Potion", "Leather Scraps"]
Массивы могут содержать элементы любого типа данных, в нашем примере выше у нас есть List
строк.
Вертикальный синтаксис
Иногда, когда мы создаем списки вручную, их может быть трудно прочитать, если все элементы находятся в одной строке кода. Мы можем объявить массив, используя несколько строк, если хотим:
flower_types = [
"daffodil",
"rose",
"chrysanthemum"
]
Имейте в виду, что это всего лишь изменение стиля. Код будет работать правильно в любом случае.
Счет в программировании
В мире программирования считать немного странно!
Мы не начинаем считать с 1
, вместо этого мы начинаем с 0
.
Индексы
Каждый элемент в массиве имеет индекс, указывающий на его место в массиве.
В качестве примера возьмем следующий массив:
names = ["Bob", "Lane", "Alice", "Breanna"]
- Индекс 0:
Боб
- Указатель 1:
Лейн
- Индекс 2:
Алиса
- Указатель 3:
Бреанна
Индексация в списках
Теперь, когда мы знаем, как создавать новые списки, нам нужно знать, как получить доступ к определенным элементам в списке.
Мы получаем доступ к элементам в списке напрямую, используя их индекс. Индексы начинаются с 0 (первый элемент) и увеличиваются на единицу с каждым последующим элементом. Синтаксис следующий:
best_languages = ["JavaScript", "Go", "Rust", "Python", "C"]
print(best_languages[1])
# prints "Go", because index 1 was provided
Длина списка
Длина списка может быть рассчитана с помощью функции len()
. Опять же, мы подробно рассмотрим функции позже, но вот синтаксис:
fruits = ["apple", "banana", "pear"]
length = len(fruits)
# Prints: 3
Длина списка равна количеству присутствующих элементов. Пусть вас не смущает тот факт, что длина не равна индексу последнего элемента, на самом деле она всегда будет на единицу больше.
Список обновлений
Мы также можем изменить элемент, существующий по заданному индексу. Например, мы можем изменить Leather
на Leather Armor
в массиве inventory
следующим образом:
inventory = ["Leather", "Healing Potion", "Iron Ore"]
inventory[0] = "Leather Armor"
# inventory: ['Leather Armor', 'Healing Potion', 'Iron Ore']
Добавление в Python
Обычно создается пустой список, а затем заполняется значениями с помощью цикла. Мы можем добавлять значения в конец списка, используя метод .append()
:
cards = []
cards.append("nvidia")
cards.append("amd")
# the cards list is now ['nvidia', 'amd']
Всплывающие значения
.pop()
является противоположностью .append()
. Pop удаляет последний элемент из массива и возвращает его для использования. Например:
vegetables = ["broccoli", "cabbage", "kale", "tomato"];
last_vegetable = vegetables.pop()
# vegetables = ['broccoli', 'cabbage', 'kale']
# last_vegetable = 'tomato'
Подсчет элементов в списке
Помните, что мы можем перебирать (подсчитывать) все элементы массива с помощью цикла. Например, следующий код напечатает каждый элемент массива sports
.
for i in range(0, len(sports)):
print(sports[i])
Синтаксис без индекса
На мой взгляд, Python имеет наиболее элегантный синтаксис для итерации непосредственно по элементам в списке, не беспокоясь об индексах. Если вам не нужен порядковый номер, вы можете использовать следующий синтаксис:
trees = ['oak', 'pine', 'maple']
for tree in trees:
print(tree)
# Prints:
# oak
# pine
# maple
tree
, переменная, объявленная с использованием ключевого слова in
, напрямую обращается к значению в массиве, а не к индексу значения. Если нам не нужно обновлять элемент, а нужно только получить доступ к его значению, то это более чистый способ написания кода.
Найти элемент в списке
Пример синтаксиса "без индекса" или "без диапазона":
for fruit in fruits:
print(fruit)
Оператор по модулю в Python
Для поиска остатка можно использовать оператор по модулю:
Например, 7
по модулю 2
будет < code>1, потому что 2 можно без остатка умножить на 7 максимум 3 раза:
2 * 3 = 6
Тогда остается 1 осталось, чтобы перейти от 6
к 7
.
7–6 = 1
Оператор d — это знак процента: %
. Однако важно понимать, что модуль не является процентом! Это просто символ, который мы используем.
remainder = 8 % 3
# remainder = 2
Нечетное число – это число, которое при делении на 2
дает остаток не 0
.
Нарезка списков
Python позволяет легко нарезать и нарезать списки, чтобы работать только с тем разделом, который вам нужен. Один из способов сделать это — использовать простой оператор среза, который представляет собой просто двоеточие :
.
С помощью этого оператора вы можете указать, где начинать и заканчивать фрагмент, а также как пошагово перемещаться по оригиналу. Нарезка списка возвращает новый список из существующего списка.
Синтаксис следующий:
Lst[ Initial : End : IndexJump ]
scores = [50, 70, 30, 20, 90, 10, 50]
# Display list
print(scores[1:5:2])
# Prints [70, 20]
Вышеизложенное звучит так: "Дайте мне фрагмент списка оценок
от индекса 1 до 5, но не включая его, пропустив каждое второе значение. Все разделы являются необязательными эм>.
scores = [50, 70, 30, 20, 90, 10, 50]
# Display list
print(scores[1:5])
# Prints [70, 30, 20, 90]
scores = [50, 70, 30, 20, 90, 10, 50]
# Display list
print(scores[1:])
# Prints [70, 30, 20, 90, 10, 50]
Операции со списками — Объединение
Объединение двух списков (смешивание их вместе) очень просто в Python, просто используйте оператор +
.
all = [1, 2, 3] + [4, 5, 6]
print(all)
# Prints: [1, 2, 3, 4, 5, 6]
Операции со списком — содержит
Проверить, существует ли значение в списке, также очень просто в Python, просто используйте ключевое слово in
.
fruits = ["apple", "orange", "banana"]
print("banana" in fruits)
# Prints: True
Совет: кавычки внутри кавычек
Чтобы использовать кавычки внутри кавычек, их нужно либо экранировать< /a> или вам нужно использовать другие виды кавычек. Поскольку мы обычно используем двойные кавычки, мы можем вкладывать строки в одинарные кавычки:
f"banana is in fruits list: {'banana' in fruits}"
Удаление списка
В Python есть встроенное ключевое слово del
, которое удаляет элементы из объектов. В случае со списком вы можете удалить определенные индексы или целые фрагменты.
nums = [1, 2, 3, 4, 5, 6, 7, 8, 9]
# delete the fourth item
del nums[3]
print(nums)
# Output: [1, 2, 3, 5, 6, 7, 8, 9]
# delete items from 2nd to 3rd
nums = [1, 2, 3, 4, 5, 6, 7, 8, 9]
del nums[1:3]
print(nums)
# Output: [1, 4, 5, 6, 7, 8, 9]
# delete all elements
nums = [1, 2, 3, 4, 5, 6, 7, 8, 9]
del nums[:]
print(nums)
# Output: []
Кортежи
Кортежи — это упорядоченные и неизменяемые наборы данных. Вы можете думать о кортеже как о List
с фиксированным размером. Кортежи создаются с помощью круглых скобок:
my_tuple = ("this is a tuple", 45, True)
print(my_tuple[0])
# this is a tuple
print(my_tuple[1])
# 45
print(my_tuple[2])
# True
Хотя обычно считается плохой практикой хранить элементы разных типов в списке, это не проблема с кортежами. Поскольку они имеют фиксированный размер, легко отслеживать, какие индексы хранят какие типы данных.
Кортежи часто используются для хранения очень небольших групп (например, 2 или 3 элемента) данных. Например, вы можете использовать кортеж для хранения клички и возраста собаки.
dog = ("Fido", 4)
Поскольку кортежи содержат свои данные, в списке может храниться несколько кортежей. Как и при хранении других данных в списках, каждый кортеж в списке отделяется запятой.
my_tuples = [("this is the first tuple in the list", 45, True),("this is the second tuple in the list", 21, False)]
print(my_tuples[0][0])
# this is the first tuple in the list
Глава 7: Функции
Функции позволяют нам повторно использовать и организовывать код. Например, давайте представим, что нам нужно вычислить площадь круга. Мы можем использовать формулу площадь = pi * r^2
или в коде:
r = 5
area = 3.14 * r * r
Это прекрасно работает! Проблема возникает, когда несколько мест в нашем коде должны получить площадь круга
r = 5
area1 = 3.14 * r * r
r2 = 7
area2 = 3.14 * r2 * r2
r3 = 11
area3 = 3.14 * r3 * r3
Мы хотим использовать один и тот же код, зачем повторять работу?
Давайте объявим новую функцию area_of_circle()
. Обратите внимание, что ключевое слово def
пишется перед именем функции и сообщает компьютеру, что мы объявляем или определяем новую функцию.
def area_of_circle(r):
return 3.14 * r * r
Функция area_of_circle
принимает один ввод (который также можно назвать параметром или аргументом) и возвращает один вывод. Мы задаем нашей функции радиус круга и получаем площадь этого круга!
Чтобы использовать или "вызвать" функцию, мы можем передать любое число в качестве входных данных и зафиксировать выходные данные. в новую переменную:
radius = 5
area = area_of_circle(radius)
Давайте рассмотрим этот пример кода шаг за шагом.
- Переменная
radius
создается со значением5
. - Функция
area_of_circle
вызывается с одним аргументом:radius
- Выполняется функция
area_of_circle
, гдеr
равно5
- Результат
3,14 * r * r
возвращается изarea_of_circle
, который равен78,75
area_of_circle(radius)
преобразуется в возвращаемое значение78,75
- Переменная
area
создается со значением78,75
.
Несколько параметров
Функции могут иметь несколько параметров или входных данных:
def subtract(a, b):
return a - b
Где объявлять функции
Вы, наверное, заметили, что переменная должна быть объявлена перед ее использованием. Например, следующее не работает:
print(my_name)
my_name = 'Lane Wagner'
Это должно быть:
my_name = 'Lane Wagner'
print(my_name)
Строки кода выполняются в порядке сверху вниз, поэтому перед использованием необходимо создать переменную. Это означает, что если вы определяете функцию, вы не можете вызывать эту функцию до тех пор, пока она не будет определена.
Функция main()
— это соглашение, используемое во многих языках программирования для указания точки входа приложения. Определяя одну функцию main
и вызывая main()
только в конце всей программы, мы гарантируем, что все наши функции определены до их вызова.< /p>
Порядок функций
Все функции должны быть определены до их использования.
Вы можете подумать, что это затруднит структурирование кода Python, потому что порядок, в котором объявляются функции, может быстро стать настолько зависимым друг от друга, что написание чего-либо становится невозможным.
Как оказалось, большинство разработчиков Python решают эту проблему, просто сначала определяя все функции, а затем, наконец, вызывая функцию точки входа последней. Если вы сделаете это, то порядок объявления функций в не имеет значения. Функция точки входа обычно называется «основной».
def main():
func2()
def func2():
func3()
def func3():
print("I'm function 3")
main() # entrypoint
Область
Область действия — это где имя переменной или функции доступно для использования. Например, когда мы создаем переменные в функции (например, давая имена нашим параметрам), эти данные недоступны вне этой функции.
Например:
def subtract(x, y)
return x - y
result = subtract(5, 3)
print(x)
# ERROR! "name 'x' is not defined"
При вызове функции subtract
переменной x
присваивается значение 5, но x
существует только в коде внутри функцию вычесть
. Если мы попытаемся напечатать x
вне этой функции, мы не получим результата, на самом деле мы получим большую ошибку.
https://www.youtube.com/watch?v=CKv_WHCcR-w&embedable =правда
Глобальный охват
До сих пор мы работали в глобальном масштабе. Это означает, что когда мы определяем переменную или функцию, это имя доступно в любом другом месте в нашей программе, даже внутри других функций.
Например:
pi = 3.14
def get_area_of_circle(radius):
return pi * radius * radius
Поскольку pi
был объявлен в родительской "глобальной" области видимости, его можно использовать в функции get_area_of_circle()
.
Бесконечность
Встроенная функция float()
может использоваться для создания числовое значение с плавающей запятой, представляющее отрицательное значение бесконечности. Я добавил его для вас в качестве отправной точки.
negative_infinity = float('-inf')
positive_infinity = float('inf')
Нет возврата
Если в функции не указано возвращаемое значение (например, это может быть функция, которая выводит некоторый текст на консоль, но не возвращает значение явно), она вернет None
. Все следующие фрагменты кода возвращают одно и то же:
def my_func():
print("I do nothing")
return None
def my_func():
print("I do nothing")
return
def my_func():
print("I do nothing")
Параметры и аргументы
Параметры – это имена, используемые для входных данных при определении функции. Аргументы — это имена входных данных, предоставляемых при вызове функции.
Напомним, что аргументы — это фактические значения, которые передаются функции, например, 42.0
, "темный рыцарь"
или True
. Параметры — это имена, которые мы используем в определении функции для ссылки на те значения, которые на момент написания функции могут быть любыми.
Тем не менее, важно понимать, что это все семантика, и, откровенно говоря, разработчики очень ленивы с этими определениями. Вы часто будете слышать, что слова аргументы и параметры взаимозаменяемы.
# a and b are parameters
def add(a, b)
return a + b
# 5 and 6 are arguments
sum = add(5, 6)
Несколько возвращаемых значений
В Python мы можем возвращать более одного значения из функции. Все, что нам нужно сделать, это отделить каждое значение запятой.
# returns email, age, and status of the user
def get_user():
return "name@domain.com", 21, "active"
email, age, status = get_user()
print(email, age, status)
# Prints: "name@domain.com 21 active"
def get_user():
return "name@domain.com", 21, "active"
# this works, and by convention you should NOT use the underscore variable later
email, _, _ = get_user()
print(email)
# Prints: "name@domain.com"
print(_)
# Prints: "active"
Значения по умолчанию для аргументов функции
В Python есть способ указать значение по умолчанию для аргументов функции. Это может быть удобно, если функция имеет аргументы, которые по существу являются «необязательными», и вы, как создатель функции, хотите использовать определенное значение по умолчанию на случай, если вызывающая сторона не предоставит его.
Значение по умолчанию создается с помощью оператора присваивания (=
) в сигнатуре функции.
def get_greeting(email, name="there"):
return f"Hello {name}, welcome! You've registered your email: {email}"
msg = get_greeting("lane@example.com", "Lane")
# Hello Lane, welcome! You've registered your email: lane@example.com
msg = get_greeting("lane@example.com")
# Hello there, welcome! You've registered your email: lane@example.com
Если второй параметр опущен, вместо него будет использоваться значение по умолчанию "there"
. Как вы могли догадаться, для работы этой структуры необязательные аргументы, для которых заданы значения по умолчанию, идут после всех обязательных аргументов.
Глава 8. Словари
Словари в Python используются для хранения значений данных в key
-> пары value
. Словари — отличный способ хранения групп информации.
car = {
"brand": "Tesla",
"model": "3",
"year": 2019
}
Повторяющиеся ключи
Поскольку словари используют уникальные ключи, в одном словаре не может быть двух одинаковых ключей. Если вы попытаетесь использовать один и тот же ключ дважды, связанное значение будет просто перезаписано.
Доступ к значениям словаря
Элементы словаря должны быть каким-то образом доступны в коде, иначе они не будут очень полезны.
Значение извлекается из словаря путем указания соответствующего ключа в квадратных скобках. Синтаксис похож на индексацию в списке.
car = {
'make': 'tesla',
'model': '3'
}
print(car['make'])
# Prints: tesla
Установка значений словаря
Вам не нужно создавать словарь со значениями, которые уже есть внутри. Обычно пустой словарь создается, а затем заполняется динамическими значениями. Синтаксис такой же, как при получении данных из ключа, просто используйте оператор присваивания (=
), чтобы присвоить этому ключу значение.
names = ["jack bronson", "jill mcarty", "john denver"]
names_dict = {}
for name in names:
# .split() returns a list of strings
# where each string is a single word from the original
names_arr = name.split()
# here we update the dictionary
names_dict[names_arr[0]] = names_arr[1]
print(names_dict)
# Prints: {'jack': 'bronson', 'jill': 'mcarty', 'john': 'denver'}
Обновление значений словаря
Если вы попытаетесь установить значение уже существующего ключа, вы просто обновите значение этого ключа.
names = ["jack bronson", "james mcarty", "john denver"]
names_dict = {}
for name in names:
# .split() returns a list of strings
# where each string is a single word from the original
names_arr = name.split()
# we're always setting the "jack" key
names_dict["jack"] = names_arr[1]
print(names_dict)
# Prints: {'jack': 'denver'}
Удаление значений словаря
Вы можете удалить существующие ключи с помощью ключевого слова del
.
names_dict = {
'jack': 'bronson',
'jill': 'mcarty',
'joe': 'denver'
}
del names_dict['joe']
print(names_dict)
# Prints: {'jack': 'bronson', 'jill': 'mcarty'}
Удаление несуществующих ключей
Обратите внимание: если вы попытаетесь удалить несуществующий ключ, вы получите ошибку.
names_dict = {
'jack': 'bronson',
'jill': 'mcarty',
'joe': 'denver'
}
del names_dict['unknown']
# ERROR HERE, key doesn't exist
Проверка существования
Если вы не уверены, существует ли ключ в словаре, используйте ключевое слово in
.
cars = {
'ford': 'f150',
'tesla': '3'
}
print('ford' in cars)
# Prints: True
print('gmc' in cars)
# Prints: False
Перебор словаря в Python
fruit_sizes = {
"apple": "small",
"banana": "large",
"grape": "tiny"
}
for name in fruit_sizes:
size = fruit_sizes[name]
print(f"name: {name}, size: {size}")
# name: apple, size: small
# name: banana, size: large
# name: grape, size: tiny
По порядку или без?
Начиная с версии Python 3.7
словари упорядочены. В Python 3.6
и более ранних версиях словари были неупорядочены.
Поскольку словари упорядочены, элементы имеют определенный порядок, и этот порядок не изменится.
Неупорядоченный означает, что элементы, используемые для не, имеют определенный порядок, поэтому вы не можете ссылаться на элемент с помощью индекса.
Вывод: если вы используете Python 3.7
или более позднюю версию, вы сможете каждый раз перебирать словари в одном и том же порядке.
Глава 9: Наборы
Наборы подобны спискам, но они неупорядочены и гарантируют уникальность. В наборе не может быть двух одинаковых значений.
fruits = {'apple', 'banana', 'grape'}
print(type(fruits))
# Prints: <class 'set'>
print(fruits)
# Prints: {'banana', 'grape', 'apple'}
Добавление значений в набор
fruits = {'apple', 'banana', 'grape'}
fruits.add('pear')
print(fruits)
# Prints: {'banana', 'grape', 'pear', 'apple'}
Пустой набор
Поскольку синтаксис {}
создает пустой словарь, чтобы создать пустой набор, просто используйте функцию set()
.
fruits = set()
fruits.add('pear')
print(fruits)
# Prints: {'pear'}
Перебирать значения в наборе (порядок не гарантируется)
fruits = {'apple', 'banana', 'grape'}
for fruit in fruits:
print(fruit)
# Prints:
# banana
# grape
# apple
Удаление значений из набора
fruits = {'apple', 'banana', 'grape'}
fruits.remove('apple')
print(fruits)
# Prints: {'banana', 'grape'}
Глава 10. Ошибки
Вы, вероятно, время от времени сталкивались с некоторыми ошибками в своем коде, если вы дошли до этого места в курсе. В Python различаются два основных типа ошибок.
- синтаксические ошибки
- исключения
Синтаксические ошибки
Возможно, вы уже знаете, что это такое. Синтаксическая ошибка — это всего лишь сообщение интерпретатора Python о том, что ваш код не соответствует правильному синтаксису Python.
this is not valid code, so it will error
Если я попытаюсь запустить это предложение, как если бы это был допустимый код, я получу синтаксическую ошибку:
this is not valid code, so it will error
^
SyntaxError: invalid syntax
Исключения
Даже если ваш код имеет правильный синтаксис, он все равно может вызвать ошибку при попытке его выполнения. Ошибки, обнаруженные во время выполнения, называются «исключениями» и могут корректно обрабатываться вашим кодом. Вы даже можете создавать свои собственные исключения, когда в вашем коде происходят плохие вещи.
Python использует шаблон try-except для обработки ошибок.
try:
10 / 0
except Exception as e:
print(e)
# prints "division by zero"
Блок try
выполняется до тех пор, пока не возникнет исключение или он не завершится, в зависимости от того, что произойдет раньше. В этом случае возникает ошибка «делить на ноль», потому что деление на ноль невозможно. Блок except
выполняется только в том случае, если в блоке try
возникает исключение. Затем он предоставляет исключение в виде данных (в нашем случае e
), чтобы программа могла корректно обработать исключение без сбоев.
Создание собственных исключений
Ошибок не следует бояться. Ожидается, что каждая программа, работающая в производственной среде, будет постоянно управлять ошибками. Наша работа как разработчиков заключается в корректной обработке ошибок таким образом, чтобы это соответствовало ожиданиям наших пользователей.
Ошибки НЕ являются ошибками
https://www.youtube.com/watch?v=k23hjyvvhcA&embedable=true а>
Когда в нашем собственном коде происходит что-то, чего мы не ожидаем, мы должны создавать собственные исключения. Например, если кто-то передает неправильные входные данные в написанную нами функцию, мы не должны бояться вызвать исключение, чтобы сообщить им, что они сделали что-то не так.
ошибка или исключение возникает, когда происходит что-то плохое, но пока наш код обрабатывает это так, как ожидают пользователи, это не ошибка . Ошибка — это когда код ведет себя не так, как ожидают пользователи.
Например, если игрок пытается выковать железный меч из бронзового металла, мы можем вызвать исключение и показать игроку сообщение об ошибке. Однако это ожидаемое поведение игры, так что это не ошибка. Если игрок может выковать железный меч из бронзы, это можно считать ошибкой, потому что это противоречит правилам игры.
raise Exception("something bad happened")
Программные приложения несовершенны, а ввод данных пользователем и сетевое подключение далеко не предсказуемы. Несмотря на интенсивную отладку и модульное тестирование, приложения все равно будут иметь сбои.
Потеря сетевого подключения, отсутствующие строки базы данных, проблемы с нехваткой памяти и неожиданные действия пользователя могут помешать нормальной работе приложения. Ваша задача — изящно перехватывать и обрабатывать любые исключения, чтобы ваше приложение продолжало работать. Когда вы можете обнаружить, что что-то не так, вы должны сами вызывать ошибки в дополнение к исключениям «по умолчанию», которые будет вызывать интерпретатор Python.
raise Exception("something bad happened")
#Различные типы исключений
Мы еще не рассмотрели классы и объекты, а это то, чем на самом деле является Exception
. Подробнее об этом мы поговорим в следующем курсе объектно-ориентированного программирования, который мы подготовили для вас.
На данный момент важно понимать, что существуют разные типы исключений и что мы можем различать их в нашем коде.
Дополнительный синтаксис для ошибок
try:
10/0
except ZeroDivisionError:
print("0 division")
except Exception:
print("unknown exception")
try:
nums = [0, 1]
print(nums[2])
except ZeroDivisionError:
print("0 division")
except Exception:
print("unknown exception")
Что будет напечатано:
0 division
unknown exception
Глава 11. Факты о Python
Дзен Python
Тим Питерс, давний питонист, описывает основные принципы Python в своей знаменитой короткой статье Дзэн Питон.
<цитата>Красивое лучше безобразного.
Явное лучше, чем неявное.
Простое лучше, чем сложное.
Сложное лучше сложного.
Плоский лучше, чем вложенный.
Разреженный лучше, чем плотный.
Удобочитаемость важна.
Особые случаи не настолько особенные, чтобы нарушать правила.
Хотя практичность важнее чистоты.
Ошибки никогда не должны проходить молча.
Если явно не отключено.
Перед лицом двусмысленности не поддавайтесь искушению угадать.
Должен быть один -- и желательно только один -- очевидный способ сделать это.
Хотя поначалу это может быть неочевидно, если вы не голландец.
Сейчас лучше, чем никогда.
Хотя никогда лучше, чем прямо сейчас сейчас.
Если реализацию сложно объяснить, это плохая идея.
Если реализацию легко объяснить, это может быть хорошей идеей.
Пространства имен — это отличная идея. Давайте сделаем больше таких!
Почему Python?
Вот несколько причин, по которым мы считаем Python перспективным выбором для разработчиков:
- Легко читать и писать — Python читается как простой английский. Благодаря простому синтаксису это отличный выбор для реализации передовых концепций, таких как ИИ. Возможно, это лучшая функция Python.
- Популярность. Согласно опросу разработчиков Stack Overflow, Python занимает 4-е место по популярности. язык в 2020 году.
- Бесплатно. Python, как и многие современные языки, разрабатывается под лицензией с открытым исходным кодом. Его можно бесплатно установить, использовать и распространять.
- Портативный — Python, написанный для одной платформы, будет работать на любой другой платформе.
- Интерпретируемый. Код можно выполнять сразу после его написания. Поскольку для компиляции не требуется много времени, как в Java, C++ или Rust, выпуск кода в рабочую среду обычно происходит быстрее.
Почему не Python?
Python может быть не лучшим выбором для проекта, если:
- Код должен работать быстро. Код Python выполняется очень медленно, поэтому критически важные для производительности приложения, такие как компьютерные игры, не пишутся на Python.
- Кодовая база станет большой и сложной. Из-за динамической системы типов в коде Python сложнее содержать ошибки.
- Приложение должно распространяться непосредственно среди нетехнических пользователей. Им пришлось бы установить Python, чтобы запустить ваш код, что было бы огромным неудобством.
Python 2 против Python 3
Одна вещь, о которой важно помнить, продолжая знакомство с Python, заключается в том, что экосистема Python страдает от синдрома раздвоения личности. Python 3 был выпущен 3 декабря 2008 года, но более десяти лет спустя Интернет по-прежнему полон зависимостей, скриптов и руководств по Python 2.
В этом курсе мы использовали Python 3 — как и любой хороший гражданин в наши дни.
Одним из наиболее очевидных критических изменений между Python 2 и Python 3 является синтаксис для вывода текста на консоль.
Питон 2
print "hello world"
Питон 3
print("hello world")
Поздравляем с завершением!
Если вы заинтересованы в выполнении интерактивных заданий по программированию и викторинах для этого курса, вы можете ознакомиться с курсом Learn Python на странице Boot. .dev.
Этот курс является частью моего полного карьерного пути бэкенд-разработчика, состоящего из других курсов и проектов, если вам интересно проверить их.
:::информация Также опубликовано здесь.
:::
Оригинал