Содержание
- 1 Является ли жадный алгоритм лучшим? Жадность всегда работает?
- 2 Алгоритм Дейкстры
- 3 Цикл for в Python
- 4 Цикл for
- 5 Цикл с предусловием while
- 6 Пропущенные выражения в цикле
- 7 Операторы прерывания и продолжения цикла break и continue
- 8 Графический способ описания алгоритмов
- 9 Циклы
- 10 While в Паскале — цикл с предусловием
- 11 Цикл с постусловием do…while
- 12 Вложенные циклы
Является ли жадный алгоритм лучшим? Жадность всегда работает?
То что оптимально на локальном уровне, иногда не оптимально на глобальном уровне. В алгоритме подсчете сдачи мы можем определить точку, в которой он не является лучшим в глобальном масштабе.
Допустим у нас есть условие:
пусть у нас будет монеты трех номиналов .
И нас попросим выдать сдачу в 30 пенсов. Теперь посмотрим, что вернет наш алгоритм.
То есть он выбирает 1x25p и 5x1p. Хотя лучшим решением будет — 2х15р.
Наш алгоритм потерпел неудачу, потому что он вообще не смотрел на 15p. Он первым делом посмотрел на 25р и подумал: «Да, это подходит. Давайте возьмем это».
Затем он посмотрел на 15p и подумал, что «это не подходит, давайте двигаться дальше» (так как 25 + 15 > 30).
Это пример того, где жадные алгоритмы не лучший выбор.
Чтобы обойти это, вам нужно будет либо создать валюту, где это не работает, либо использовать перебор решений. Или используйте динамическое программирование.
Но жадные алгоритмы иногда могут быть лучшими на глобальном уровне то есть глобально оптимальными . Ранее мы видели, что эти алгоритмы глобально оптимальны:
- Dijkstra’s Algorithm
- Kruskal’s algorithm
- Prim’s algorithm
- Huffman trees
Существуют и другие глобально оптимальные решения, но жадные алгоритмы быстрее и проще в программировании, чем другие решения.
Алгоритм Дейкстры
Алгоритм Дейкстры находит кратчайший путь от узла ко всем остальным узлам графа. В нашем примере мы будем использовать взвешенный ориентированный граф. У каждого ребра есть направление, и у каждого ребра есть вес.
Алгоритм Дейкстры имеет много применений. Он может быть очень полезен в дорожных сетях, где вам нужно найти самый быстрый маршрут к месту. Алгоритм также используется для:
- IP Routing
- A* Algorithm
- Telephone networks
Алгоритм следует следующим правилам:
- Каждый раз, когда мы хотим посетить новый узел, мы выберем узел с наименьшим известным расстоянием.
- Как только мы переместились в узел, мы проверяем каждый из соседних узлов. Мы вычисляем расстояние от соседних узлов до корневых узлов, суммируя стоимость ребер, которые ведут к этому новому узлу.
- Если расстояние до узла меньше известного расстояния, мы обновим самое короткое расстояние.
Наш первый шаг — выбрать начальный узел. Давайте выберем A. Все расстояния назначаются равными бесконечности, так как мы пока не знаем их расстояния, пока не достигнем узла, который знает расстояние.
Мы отмечаем A в нашем списке не посещенных узлов. Расстояние от A до A равно 0. Расстояние от A до B равно 4. Расстояние от A до C равно 2. Наш список расстояний с правой стороны рисунка.
Затем мы выбираем наименьшее ребро, где вершина не была выбрана. Наименьшее ребро A ->C, и мы еще не выбрали C. Далее мы посещаем С.
Обратите внимание, как мы выбираем наименьшее расстояние от нашего текущего узла до узла, который мы еще не посетили. Мы жадные
В этом случае жадный метод является глобальным оптимальным решением.
Мы можем добраться до B из C. Теперь нам нужно выбрать минимум. min(4, 2 + 1) = 3.
Поскольку A->C->B меньше, чем A->B, мы обновляем B этой информацией. Затем мы добавляем расстояния от других узлов, которые теперь можем достичь.
Наша следующая наименьшая вершина с узлом, который мы еще не посетили, это B, с 3. Мы посещаем B.
Мы делаем то же самое для B. Затем мы выбираем самую маленькую вершину, которую мы еще не посетили, D.
На этот раз мы не обновляем расстояния. Наш последний узел тогда E.
Там нет обновлений снова. Чтобы найти кратчайший путь от A до других узлов, мы пройдемся по нашему графику.
Сначала мы выбираем A, затем C, а затем B. Если вам нужно создать кратчайший путь от A до каждого другого узла в виде графика, вы можете запустить этот алгоритм, используя таблицу с правой стороны.
Используя эту таблицу легко нарисовать кратчайшее расстояние от A до каждого другого узла на графике:
Цикл for в Python
Оператор for является одним из двух операторов, используемых для создания циклов в Python, другим является оператор while. Если вы совсем не знакомы с итерациями в Python, то рекомендуем почитать статью Итерации в Python: операторы for, while, break и continue которая будет хорошей отправной точкой для изучения циклов и итераций.
Простой цикл for
Давайте начнем с простого цикла for, который перебирает список строк и печатает каждую строку.
>>> for word in : ... print(word) ... You are awesome!
Как видите, цикл перебирает все слова в списке и печатает их. То есть на каждом шаге цикла переменной word присваивается элемент списка, а затем выполняется кодовый блок. Поскольку список — это упорядоченная последовательность элементов, цикл проходит по ним в том же порядке.
Цикл for с условием else
В Python цикл for может иметь необязательное условие else. Кодовый блок в предложении else выполняется после завершения цикла for, то есть после того, как все элементы итерируемого элемента были исчерпаны. Теперь давайте посмотрим, как мы можем расширить предыдущий пример, чтобы включить условие else.
>>> for word in : ... print(word) ... else: ... print("See you later!") ... You are awesome! See you later!
Когда полезно условие else?
Как вы могли заметить, блок else выполняется после завершения цикла for. Так какой смысл использовать блок else? Разве не будет выполнен следующий набор операторов после цикла for?
Ну, во многих случаях у нас возникают ситуации, когда нам нужно выйти из цикла for, когда выполняется определенное условие. И если это условие никогда не выполняется, но нам все равно нужно выполнить набор операторов. Для этого мы обычно используем логический флаг. Давайте посмотрим на пример.
def search(search_list, search_item): found_item = False for word in search_list: if word == search_item: found_item = True print("Found word '{}'".format(search_item)) break if not found_item: print("Word '{}' was not found!".format(search_item))
Использование:
>>> search(, "are") Found word 'are' >>> search(, "we") Word 'we' was not found!
С помощью блока else мы можем избежать использования логического флага found_item. Давайте посмотрим, как мы можем переписать вышеуказанный метод с помощью else
Обратите внимание, что блок else будет пропущен, если в цикле for встречается оператор break
def search(search_list, search_item): for word in search_list: if word == search_item: print("Found word '{}'".format(search_item)) break else: print("Word '{}' was not found!".format(search_item))
Таким образом, блок else действительно полезен, только если у нас есть оператор break в цикле for, и нам нужно, чтобы выполнился набор операторов, если условие break никогда не выполнялось.
В противном случае операторы, связанные с else, просто выполняются в конце цикла for. Вы увидите это, когда мы разберем байт-код в последнем разделе этой статьи.
Синтаксис цикла for
Теперь, когда мы рассмотрели несколько основных примеров, давайте завершим этот раздел синтаксисом цикла for.
for <element> in <iterable>: <set_of_statements_1> else: <set_of_statements_2>
По сути, для каждого итерируемого элемента выполняется set_of_statements_1. Как только все элементы исчерпаны, управление переходит к блоку else и выполняется set_of_statements_2.
Обратите внимание, что предложение else является необязательным. Если блок else отсутствует, цикл завершается после того, как все элементы будут пройдены, и управление переходит к следующему оператору программы
Цикл for
Часто цикл for называют циклом со счетчиком. Этот цикл используется, когда число повторений не связано с тем, что происходит в теле цикла. Т.е. количество повторений может быть вычислено заранее (хотя оно не вычисляется).
В заголовке цикла указываются два значения. Первое значение присваивается так называемой переменной-счетчику, от этого значения начинается отсчет количества итераций (повторений). Отсчет идет всегда с шагом равным единице. Второе значение указывает, при каком значении счетчика цикл должен остановиться. Другими словами, количество итераций цикла определяется разностью между вторым и первым значением плюс единица. В Pascal тело цикла не должно содержать выражений, изменяющих счетчик.
Цикл for существует в двух формах:
for счетчик=значение to конечное_значение do тело_цикла;
for счетчик=значение downto конечное_значение do тело_цикла;
Счетчик – это переменная любого из перечисляемых типов (целого, булевого, символьного, диапазонного, перечисления). Начальные и конечные значения могут быть представлены не только значениями, но и выражениями, возвращающими совместимые с типом счетчика типы данных. Если между начальным и конечным выражением указано служебное слово to, то на каждом шаге цикла значение параметра будет увеличиваться на единицу. Если же указано downto, то значение параметра будет уменьшаться на единицу.
Количество итераций цикла for известно именно до его выполнения, но не до выполнения всей программы. Так в примере ниже, количество выполнений цикла определяется пользователем. Значение присваивается переменной, а затем используется в заголовке цикла. Но когда оно используется, циклу уже точно известно, сколько раз надо выполниться.
var i, n integer; begin write ('Количество знаков: '); readln (n); for i = 1 to n do write ('(*) '); readln end.
Цикл с предусловием while
Общая форма записи
while (Условие){ БлокОпераций;}
УсловиеУсловиеБлокОперацийУсловиеУсловияБлокаОперацийУсловиеПример на Си
1234567891011121314151617
#define _CRT_SECURE_NO_WARNINGS // для возможности использования scanf#include <stdio.h>int main() { int k; // объявляем целую переменную key int i = 1; int sum = 0; // начальное значение суммы равно 0 printf(«k = «); scanf(«%d», &k); // вводим значение переменной k while (i <= k) // пока i меньше или равно k { sum = sum + i; // добавляем значение i к сумме i++; // увеличиваем i на 1 } printf(«sum = %d\n», sum); // вывод значения суммы getchar(); getchar(); return 0;}
1234
while (1){ БлокОпераций;}
Пропущенные выражения в цикле
Также в циклах можно пропускать одно или сразу все выражения, например:
#include <iostream>
int main() { int count = 0; for (; count < 10; ) { std::cout << count << » «; ++count; }
return 0; }
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#include <iostream> intmain() { intcount=; for(;count<10;) { std::cout<<count<<» «; ++count; } return; } |
Результат:
Инициализацию счетчика мы прописали вне тела цикла, а инкремент счетчика — внутри тела цикла. В самом операторе for мы указали только условие. Иногда бывают случаи, когда не требуется объявлять счетчик цикла (потому что у нас он уже есть) или увеличивать его (так как мы увеличиваем его каким-то другим способом).
Хоть это и не часто можно наблюдать, но в операторе for можно вообще ничего не указывать. Стоит отметить, что подобное приведет к бесконечному циклу:
Вышеприведенный пример эквивалентен:
Операторы прерывания и продолжения цикла break и continue
В теле любого цикла можно использовать операторы прерывания цикла — break и продолжения цикла — continue. Оператор break позволяет выйти из цикла, не завершая его. Оператор continue позволяет пропустить часть операторов тела цикла и начать новую итерацию.Пример на Си: Вывести числа от 0 до 99 ниже главной диагонали
12345678910111213141516
#define _CRT_SECURE_NO_WARNINGS // для возможности использования scanf#include <stdio.h>int main() { for(int i=0; i<10; i++) // цикл для десятков { for (int j = 0; j < 10; j++) // цикл для единиц { if (j > i) // если число единиц больше числа десятков в числе break; // выходим из вложенного цикла и переходим к новой строке printf(«%2d «, i * 10 + j); // выводим вычисленное число (2 знакоместа) и пробел } printf(«\n»); // во внешнем цикле переводим строку } getchar(); // scanf() не использовался, return 0; // поэтому консоль можно удержать одним вызовом getchar()}
12345678910111213141516
#define _CRT_SECURE_NO_WARNINGS // для возможности использования scanf#include <stdio.h>int main() { for(int i=0; i<10; i++) // цикл для десятков { for (int j = 0; j < 10; j++) // цикл для единиц { if ((j == 5) || (j == 8)) // если число единиц в числе равно 5 или 8, continue; // переходим к следующей итерации цикла printf(«%2d «, i * 10 + j); // выводим вычисленное число (2 знакоместа) и пробел } printf(«\n»); // во внешнем цикле переводим строку } getchar(); // scanf() не использовался, return 0; // поэтому консоль можно удержать одним вызовом getchar()}
Графический способ описания алгоритмов
Для более наглядного представления алгоритма используется графический способ. Существует несколько способов графического описания алгоритмов. Наиболее широко используемым на практике графическим описанием алгоритмов является использование блок-схем. Несомненное достоинство блок схем – наглядность и простота записи алгоритма.
Каждому действию алгоритма соответствует геометрическая фигура (блочный символ). Перечень наиболее часто употребляемых символов приведен в таблице:
Название символа | Обозначениеи пример заполнения | Пояснения |
Пуск-останов | Начало, завершение алгоритма или подпрограммы | |
Ввод-вывод данных | Ввод исходных данных или вывод результатов | |
Процесс | Внутри прямоугольника записывается действие, например, расчетная формула | |
Решение | Проверка условия, в зависимости от которого меняется направление выполнения алгоритма | |
Модификация | Организация цикла | |
Предопределенный процесс | Использование ранее созданных подпрограмм | |
Комментарий | Пояснения |
Пояснения:
блок Процесс обозначает вычислительный процесс и применяется для обозначения действия или последовательности действий, изменяющих значения переменных или данных
блок Решение обозначает проверку условия
Если условие выполняется, то есть a>b, то следующим выполняется действие по стрелке «Да». Если условие не выполняется, то осуществляется переход по стрелке «Нет».
блок Модификация используется для организации циклических (повторяющихся) действий.
блок Предопределенный процесс используется для указания обращений к ранее созданным алгоритмам и программам, в том числе и библиотечным подпрограммам.
блок Ввод-Вывод. При решении задачи на компьютере ввод исходных данных может осуществляться различными способами, например, с клавиатуры, с жесткого диска, с флэш-карты т. д. Задание численных значений исходных данных называется вводом, а отображение результатов расчета на экране монитора или с помощью принтера на бумаге – выводом. Если ввод-вывод не привязан к конкретному устройству, то обозначается параллелограммом. Если необходимо указать конкретное устройство ввода или вывода, то используются специальные геометрические фигуры.
устройство ввода или вывода | дисплей | магнитный диск |
В качестве примера графического способа описания алгоритмов с помощью блок-схем запишем алгоритм нахождения площади прямоугольника:
Внутри каждого блока записывается соответствующее действие. Последовательность выполнения задается соединительной линией со стрелочкой.
Последовательность выполнения сверху вниз и слева направо принята за основную.
Если в алгоритме не нарушается основная последовательность, то стрелочки можно не указывать. В остальных случаях последовательность выполнения блоков обозначается стрелочкой обязательно. В нашем примере основная последовательность выполнения – сверху вниз.
Циклы
Последнее обновление: 19.06.2017
Циклы являются управляющими конструкциями, позволяя в зависимости от определенных условий выполнять некоторое действие множество раз. В C# имеются следующие виды циклов:
for
foreach
while
do…while
Цикл for
Цикл for имеет следующее формальное определение:
for (; ; ) { // действия }
Рассмотрим стандартный цикл for:
for (int i = 0; i < 9; i++) { Console.WriteLine($"Квадрат числа {i} равен {i*i}"); }
Первая часть объявления цикла — — создает и инициализирует счетчик i. Счетчик необязательно должен представлять тип int. Это может быть и другой числовой тип, например, float. И перед выполнением цикла его значение будет равно 0. В данном случае это то же самое, что и объявление переменной.
Вторая часть — условие, при котором будет выполняться цикл. Пока условное выражение возвращает true, будет выполняться цикл. В данном случае цикл будет выполняться, пока счетчик i не достигнет 9.
И третья часть — приращение счетчика на единицу. Опять же нам необязательно увеличивать на единицу. Можно уменьшать: .
В итоге блок цикла сработает 9 раз, пока значение i не станет равным 9. И каждый раз это значение будет увеличиваться на 1.
Нам необязательно указывать все условия при объявлении цикла. Например, мы можем написать так:
int i = 0; for (; ;) { Console.WriteLine($"Квадрат числа {++i} равен {i * i}"); }
Формально определение цикла осталось тем же, только теперь блоки в определении у нас пустые: . У нас нет инициализированной переменной-счетчика, нет условия, поэтому цикл будет работать вечно — бесконечный цикл.
Мы также можем опустить ряд блоков:
int i = 0; for (; i<9;) { Console.WriteLine($"Квадрат числа {++i} равен {i * i}"); }
Этот пример по сути эквивалентен первому примеру: у нас также есть счетчик, только создан он вне цикла. У нас есть условие выполнения цикла. И есть приращение счетчика уже в самом блоке for.
Цикл do
В цикле do сначала выполняется код цикла, а потом происходит проверка условия в инструкции while. И пока это условие истинно, цикл повторяется. Например:
int i = 6; do { Console.WriteLine(i); i--; } while (i > 0);
Здесь код цикла сработает 6 раз, пока i не станет равным нулю
Но важно отметить, что цикл do гарантирует хотя бы единократное выполнение действий, даже если условие в инструкции while не будет истинно. То есть мы можем написать:
int i = -1; do { Console.WriteLine(i); i--; } while (i > 0);
Хотя у нас переменная i меньше 0, цикл все равно один раз выполнится.
Цикл while
В отличие от цикла do цикл while сразу проверяет истинность некоторого условия, и если условие истинно, то код цикла выполняется:
int i = 6; while (i > 0) { Console.WriteLine(i); i--; }
Операторы continue и break
Иногда возникает ситуация, когда требуется выйти из цикла, не дожидаясь его завершения. В этом случае мы можем воспользоваться оператором break.
Например:
for (int i = 0; i < 9; i++) { if (i == 5) break; Console.WriteLine(i); }
Хотя в условии цикла сказано, что цикл будет выполняться, пока счетчик i не достигнет значения 9, в реальности цикл сработает 5 раз. Так как при достижении счетчиком i значения 5, сработает оператор break, и цикл завершится.
0 1 2 3 4
Теперь поставим себе другую задачу. А что если мы хотим, чтобы при проверке цикл не завершался, а просто пропускал текущую итерацию. Для этого мы можем воспользоваться оператором continue:
for (int i = 0; i < 9; i++) { if (i == 5) continue; Console.WriteLine(i); }
В этом случае цикл, когда дойдет до числа 5, которое не удовлетворяет условию проверки, просто пропустит это число и перейдет к следующей итерации:
0 1 2 3 4 6 7 8
While в Паскале — цикл с предусловием
Пример: Определить количество цифр в введенном целом числе, не превышающем 2000000.
Алгоритм: Отделяем и удаляем последовательно последнюю цифру, наращивая счетчик.
n | счетчик |
246 | |
24 | 1 |
2 | 2 |
3 |
В чем сложность?: Заранее не определено и неизвестно, сколько цифр нужно убрать, т.е. сколько шагов необходимо сделать.Как выполнить: Надо перестать отделять цифры, когда n = 0, т.е. надо выполнять пока n > 0
Блок-схема решения:
Блок-схема решения
Решение примера на Паскале:
Цикл в Паскале применяется для создания повторений с неизвестным заранее их числом. Повторения () будут осуществляться, пока истинно некоторое условие.
Блок-схема, соответствующая циклу while в Паскале:
- Здесь оператор, стоящий после служебного слова , образует тело цикла и будет выполняться, пока значение равно (истина).
- Если операторов должно быть несколько, тогда необходимо применять .
- Условие пересчитывается каждый раз при входе в цикл.
- Непосредственно цикла может быть переменная или .
- Операторы тела цикла выполнятся только в том случае, если условие будет истинно, если условие ложно — они игнорируются, и программа продолжается с тех операторов, которые стоят уже после конструкции. Таким образом, это существенное отличие цикла с предусловием от .
Рассмотрим использование цикла в Паскале на решенном примере:
Пример: Печатать «ноль» указанное количество раз
Показать решение:
1 2 3 4 5 6 7 8 9 10 |
var i,ninteger; begin write ('kolichestvo znakov'); readln(n); i=1; while i<=n do begin {составной оператор} write(); i=i+1 end; end. |
Задача 3. Ввести целое число и найти сумму его цифр.Пример:
Введите целое число: 1234 Сумма цифр числа 1234 равна 10.
Можно использовать сложные условия:
Задача 4. Вычислять с использованием цикла while квадратные корни из чисел 900, 893, 886, 879 и т.д. до тех пор, пока это можно делать.
Детальный разбор работы цикла While в Паскале рассмотрен в видеоуроке:
Пример: найти сумму всех элементов последовательности:
которые по модулю больше 0,001:
Алгоритм:
Блок-схема решения:
Блок-схема решения
Решение на Паскале:
Решение на Паскале
Задача 5: Вычислить сумму элементов следующей последовательности с точностью 0,001:
Результат: S = 1.157
Вложенные циклы в Паскале
Существует возможность использования вложенных циклов в Паскале, когда в теле одного цикла вместо оператора стоит другой цикл.
Важно: Главным обстоятельством во вложенных циклах является использование разных переменных для счетчиков внутреннего и внешнего циклов
Рассмотрим пример:
Пример: Вывести таблицу умножения, используя вложенные циклы в паскале.
Показать решение:
1 2 3 4 5 6 7 8 9 10 |
const n = 9; {размер таблицы} var i, j integer; begin for i=1 to n do {номера строк} begin for j=1 to n do {номера столбцов} write(i*j4); writeln; {переход на новую строку} end; end. |
Цикл с постусловием do…while
Общая форма записи
do { БлокОпераций;} while (Условие);
do…whileУсловиеБлока ОперацийУсловиеdo…whileПример на Си
123456789101112131415
#define _CRT_SECURE_NO_WARNINGS // для возможности использования scanf#include <stdio.h>#include <stdlib.h> // для использования функции system()int main() { int num; // объявляем целую переменную для числа system(«chcp 1251»); // переходим на русский язык в консоли system(«cls»); // очищаем экран do { printf(«Введите число от 0 до 10: «); // приглашение пользователю scanf(«%d», &num); // ввод числа } while ((num < 0) || (num > 10)); // повторяем цикл пока num<0 или num>10 printf(«Вы ввели число %d», num); // выводим введенное значение num — от 0 до 10 getchar(); getchar(); return 0;}
Вложенные циклы
Итак, мы с вами рассмотрели два оператора циклов: while и for. Все эти циклы можно комбинировать друг с другом. То есть, создавать вложенные циклы (цикл внутри цикла).
Как это работает? Представьте, что бегун начинает бежать по большому кругу, но затем, для продолжения бега, ему необходимо сделать еще несколько вложенных кругов, после чего он возвращается на большой круг и продолжает свой бег.
В частности, такие вложенные циклы очень полезны для перебора элементов матрицы
Тогда мы делаем первый цикл от 1 до N и вложенный от 1 до M
A = 1,2,3, 4,5,6 N=2; M=3 for i in range(N): for j in range(M): print(Aij) print()
Или для подсчета вот такой двойной суммы ряда
Программа будет выглядеть так:
S=; M=10; N=5 for i in range(1,N+1): for j in range(1,M+1): S += i*j print(S)
Мы здесь сначала пробегаем все значения j от 1 до M при фиксированном i=1, затем, значение i увеличивается на 1, становится 2 и при этом i снова пробегаются значения j от 1 до M. И так пока i не превысит значение N. То есть, второй цикл вложен вот в этот первый. И таких вложений можно делать сколько угодно.
Вот так работают операторы циклов в Python и теперь вы знаете как их можно применять на практике.
Видео по теме
Python 3 #1: установка и запуск интерпретатора языка
Python 3 #2: переменные, оператор присваивания, типы данных
Python 3 #3: функции input и print ввода/вывода
Python 3 #4: арифметические операторы: сложение, вычитание, умножение, деление, степень
Python 3 #5: условный оператор if, составные условия с and, or, not
Python 3 #6: операторы циклов while и for, операторы break и continue
Python 3 #7: строки — сравнения, срезы строк, базовые функции str, len, ord, in
Python 3 #8: методы строк — upper, split, join, find, strip, isalpha, isdigit и другие
Python 3 #9: списки list и функции len, min, max, sum, sorted
Python 3 #10: списки — срезы и методы: append, insert, pop, sort, index, count, reverse, clear
Python 3 #11: списки — инструмент list comprehensions, сортировка методом выбора
Python 3 #12: словарь, методы словарей: len, clear, get, setdefault, pop
Python 3 #13: кортежи (tuple) и операции с ними: len, del, count, index
Python 3 #14: функции (def) — объявление и вызов
Python 3 #15: делаем «Сапер», проектирование программ «сверху-вниз»
Python 3 #16: рекурсивные и лямбда-функции, функции с произвольным числом аргументов
Python 3 #17: алгоритм Евклида, принцип тестирования программ
Python 3 #18: области видимости переменных — global, nonlocal
Python 3 #19: множества (set) и операции над ними: вычитание, пересечение, объединение, сравнение
Python 3 #20: итераторы, выражения-генераторы, функции-генераторы, оператор yield
Python 3 #21: функции map, filter, zip
Python 3 #22: сортировка sort() и sorted(), сортировка по ключам
Python 3 #23: обработка исключений: try, except, finally, else
Python 3 #24: файлы — чтение и запись: open, read, write, seek, readline, dump, load, pickle
Python 3 #25: форматирование строк: метод format и F-строки
Python 3 #26: создание и импорт модулей — import, from, as, dir, reload
Python 3 #27: пакеты (package) — создание, импорт, установка (менеджер pip)
Python 3 #28: декораторы функций и замыкания
Python 3 #29: установка и порядок работы в PyCharm
С этим читают