Операторы цикла в языке си

Является ли жадный алгоритм лучшим? Жадность всегда работает?

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


Допустим у нас есть условие:

пусть у нас будет монеты трех номиналов .

И нас попросим выдать сдачу в 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

Алгоритм следует следующим правилам:

  1. Каждый раз, когда мы хотим посетить новый узел, мы выберем узел с наименьшим известным расстоянием.
  2. Как только мы переместились в узел, мы проверяем каждый из соседних узлов. Мы вычисляем расстояние от соседних узлов до корневых узлов, суммируя стоимость ребер, которые ведут к этому новому узлу.
  3. Если расстояние до узла меньше известного расстояния, мы обновим самое короткое расстояние.

Наш первый шаг — выбрать начальный узел. Давайте выберем 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


С этим читают