Переменные

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

    Имя переменной может содержать буквы, цифры и символ подчеркивания и должно начинаться с буквы или подчеркивания: author, number_of_words, poem1, poem2.

    Заметки зануды
    На самом деле, все в питоне, включая «примитивные типы» и функции — это объекты, но мы пока не знакомы с ними ;)

    Переменная хранит значение определенного типа данных. Среди всех доступных типов можно условно выделить группу «примитивных типов»:

    • int — целочисленный — для целых чисел;
    • float — вещественный или тип с плавающей запятой — для чисел имеющих дробную часть;
    • str — строковый (string) — для последовательностей символов любой длины;
    • bool — логический или булев тип — для бинарных значений истина/ложь;

    Перед использованием переменная должна быть объявлена. В питоне объявлением считается первое присваивание переменной какого-либо значения. Для этого используется оператор присваивания =.

    # str - значение должно быть в кавычках
    line = "Верь тому, что сердце скажет"
    
    # пустая строка
    empty = ""
    
    # int
    year = 1984
    
    # float - дробная часть отделяется точкой
    float_number = 9.75
    
    # bool - только два значения: True или False
    is_good_poetry = True
    has_bad_rhyme = False
    	
    # None - специальное значение, обозначающее что у переменной нет значения
    nihilism = None
    

    Работа с консолью

    Ввод

    Для получения введенного пользователем значения используется функция input. Можно указать строку, которая будет выведена на экран перед получением значения. Для дальнейшей работы с полученным значением его необходимо сохранить в переменную.

    place_of_resurection = input("Где воскресну я душой? ")
    

    Значение, полученное из консоли, всегда строкового типа. Для того чтобы использовать значение как число, нужно конвертировать его функцией приведения, одноименной требуемому типу.

    # int
    # считаем строку "12"
    str_number_of_lines = input("Сколько строк в стихотворении? ")
    # преобразуем в число 12 
    number_of_lines = int(str_number_of_lines) 
    
    # float 	
    # считаем строку "27.6456"
    str_average_age = input("Каков средний возраст поэтов? ") 
    # преобразуем в число 27.6456
    average_age = float(str_average_age) 
    
    # без промежуточной переменной
    year = int(input("В каком году была война 1812 года? "))
    

    Вывод

    Заметки зануды
    На самом деле, можно указать функции print, что выводить между значениями и что выводить в конце.

    Для вывода значения в консоль используется функция print, которая может выводить несколько значений подряд, разделяя их пробелами. После вывода курсор будет переведен в начало следующей строки. Можно выводить как переменные, так и строки или числа напрямую.

    print("Там поют согласны лиры;")
    
    print(12, "стульев")
    
    word1 = "обитель"
    word2 = "тишины"
    print(word1, word2) 
    

    Результат выполнения скрипта:

    Там поют согласны лиры;
    12 стульев
    обитель тишины
    
    Это было бы интересно,
    если бы вы были программистом
    Кроме %s, есть и другие варианты, особенно актуальные для вывода дробых чисел. Например, можно указать, сколько выводить цифр после запятой.

    Можно использовать форматирование, чтобы подставить одно или несколько значений в строку-шаблон. Шаблон должен содержать %s в местах предполагаемых подстановок.

    word1 = "плоды"
    word2 = "сенистых"
    print("Там блестят %s златые / На %s деревах" % (word1, word2))
    
    Там блестят плоды златые / На сенистых деревах

    Операции с числами

    Заметки зануды
    На самом деле, операции это завуалированные функции, поэтому к ним применяется та же терминология («аргумент», «принимает» и т.д.), что и к функциям (См. главу «Функции»).

    Операции бывают унарными и бинарными. Унарная опрерация принимает один аргумент, бинарная — два.

    n = 11
    result = -n      # инверсия знака (-11)
    result = 11 + 2  # сложение
    result = 11 - 2  # вычитание
    result = 11 * 2  # умножение
    result = 11 ** 2 # возведение в степень (11 в квадрате)
    result = 11 / 2  # обычное деление (5.5)
    result = 11 // 2 # целочисленное деление (5)
    result = 11 % 2  # остаток от деления (1, потому что 11 = 5 * 2 + 1)
    

    Целочисленное деление работает не по математическим правилам — оно полностью отбрасывает дробную часть. То есть: 199 / 100 = 1.99, но 199 // 100 = 1, а не 2, как можно было бы предположить.

    Вычисление остатка от деления — очень полезная операция. Ее можно использовать, чтобы проверять четность, делимость, раскладывать число на цифры и т.д.

    Операции со строками

    Заметки зануды
    Официально сложение строк называется «конкатенация»

    Строки можно складывать (склеивать) с помощью оператора +. Получившаяся строка не будет содержать ни каких символов между склеенными строками.

    name = "Евгений"
    full_name = name + " Абрамович " + "Баратынский "
    print(full_name)
    
    Евгений Абрамович Баратынский

    Со строками можно складывать переменные других типов. Для этого их нужно сконвертировать в строку, используя функцию приведения str.

    year = 1800
    sentence = "Год рождения: " + str(year)
    print(sentence)
    
    Год рождения: 1800

    С помощью оператора * можно получить строку, состоящую из повторений исходной строки.

    laugh = "ха" * 3
    print(laugh)
    
    хахаха

    Строки могут содержать символы имеющие специальное значение при выводе на экран:

    • \n — новая строка;
    • \t — табуляция;
    • \" — двойные кавычки (чтобы отличать кавычки внутри строки от кавычек, обозначающих конец строки);
    • \\ — собственно, обратный слэш;

    escaped = "\t\\n - новая строка\n\t\\t - табуляция\n\t\\\" - \"\n\t\\\\ - \\"
    print(escaped)
    
    \n - новая строка
    \t - табуляция
    \" - "
    \\ - \
    

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

    multiline = """	\\n - новая строка
    \\t - табуляция
    \\" - "
    \\\\ - \ """
    print(multiline)
    
    \n - новая строка
    \t - табуляция
    \" - "
    \\ - \
    

    Логические выражения

    Это было бы интересно,
    если бы вы были терминоведом
    Свое название булев тип получил в честь Джорджа Буля, основоположника математической логики.

    Логическое выражение — это выражение, результатом вычисления которого является булево значение, т. е. они либо истинны, либо ложны.

    Сравнение чисел

    n1 = 1812
    n2 = 1800
    n3 = 1812
    
    # оператор "равно"
    are_equal = n1 == n2 # False
    are_equal = n1 == n3 # True
    
    # оператор "не равно"
    are_not_equal = n1 != n2 # True
    are_not_equal = n1 != n3 # False
    
    # оператор "меньше"
    is_less = n1 < n2 # False
    is_less = n1 < n3 # False
    
    # оператор "больше"
    is_greater = n1 > n2 # True
    is_greater = n1 > n3 # False
    
    # оператор "меньше или равно"
    is_less_or_equal = n1 <= n2 # False
    is_less_or_equal = n1 <= n3 # True
    
    # оператор "больше или равно"
    is_greater_or_equal = n1 >= n2 # True
    is_greater_or_equal = n1 >= n3 # True
    

    Обратите особое внимание на то, что = — это оператор присваивания значения, а == — оператор проверки равенства.

    Сравнение строк

    s1 = "хорошо"
    s2 = "плохо"
    s3 = "хорошо"
    
    # оператор "равно"
    are_equal = s1 == s2 # False
    are_equal = s1 == s3 # True
    
    # оператор "не равно"
    are_not_equal = s1 != s2 # True
    are_not_equal = s1 != s3 # False
    

    Операторы <, >, <= и >= также применимы к строкам. На первый взгляд может показаться, что строки сравниваются в соответствии с алфавитным порядком букв, т. е. одна строка меньше другой, если ее статья в словаре находится раньше. Сложности возникают, когда в строке появляются символы разных регистров и небуквенные символы: пробелы, цифры, знаки препинания и т.д. На самом деле, порядок символов определяется по их кодам в таблице символов unicode.

    Логические операции

    Аргументами логических операции могут выступать логические выражения или переменные булевого типа.

    Логическое «НЕ» (оператор not) — унарная операция, возвращающая значение, противоположное значению аргумента. Таблица истинности:

    a not a
    1 0
    0 1

    Логическое «И» (оператор and) — бинарная операция, возвращающая истину тогда, когда хотя бы один из аргументов является истинным. Таблица истинности:

    a b a and a
    1 1 1
    1 0 1
    0 1 1
    0 0 0

    Логическое «ИЛИ» (оператор or) — бинарная операция, возвращающая истину только тогда, когда оба аргумента являются истинными. Таблица истинности:

    a b a or a
    1 1 1
    1 0 0
    0 1 0
    0 0 0

    Логические операции, как и математические, можно комбинировать, при этом приоритет выполнения операторов такой:

    1. ()
    2. not
    3. and
    4. or
    Сравните таблицы истинности для выражений a or b and not c и (a or b) and not c:

    a or b and not c
    a bcnot cb and da or e
       de 
    111001
    110111
    101001
    100101
    011000
    010111
    001000
    000100
    (a or b) and not c
    abca or bnot cd and e
       de 
    111100
    110111
    101100
    100111
    011100
    010111
    001000
    000010

    Примеры:

    n1 = 150
    n2 = 300
    
    # проверяем принадлежит ли число промежутку
    in_between = n1 > 100 and n1 < 200 # True
    in_between = n2 > 100 and n2 < 200 # False
    
    # хотя для этого есть специальный синтаксис
    in_betwen = 100 < n1 < 200 # True
    
    # проверяем лежит ли число вне промежутка
    not_in_between = n1 < 100 or n1 > 200 # False
    not_in_between = n2 < 100 or n2 > 200 # True
    
    # или
    not_in_betwen = not (100 < n1 < 200) # False
    

    Ветвления. Оператор if

    Условный оператор if дает возможность выполнять разные наборы команд в зависимости от истинности условий. Условием может быть любое логическое выражение, переменная булевого типа или функция возвращающая булево значение. Общий вид условной конструкции:

    if условие:
      блок команд
    elif условие:
      блок команд
    else:
      блок команд
    

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

    В условной конструкции обязателен только оператор if; elif и else могут отсутствовать. С другой стороны, конструкция может содержать несколько блоков elif.

    Выполнение условной конструкции происходит так: питон последовательно проверяет все условия, пока не найдет истинное или не дойдет до оператора else. Затем он выполняет соответствующий блок команд и завершает выполнение конструкции. Таким образом, в любом случае может быть выполнен только один блок команд одной условной конструкции.

    Примеры.

    Проверка четности числа.

    n = int(input("Число: "))
    
    if n % 2 == 0:
        print("Четное")
    else:
        print("Нечетное")
    
    Число: 11
    Нечетное
    
    Число: 244
    Четное
    

    Согласование числительного и существительного.

    • Числа, оканчивающиеся на 1, но не на 11, требуют существительное в именительном падеже единственного числа.
    • Числа, оканчивающиеся на 2, 3, 4, но не на 12, 13, 14, требуют существительное в родительном падеже единственного числа.
    • Все остальные требуют существительное в родительном падеже множественного числа.

    age = int(input("Возраст: "))
    
    last = age % 10 # запоминаем последнюю цифру
    penult = age // 10 % 10 # запоминаем предпоследнюю цифру
    
    if last == 1 and penulte != 1:
        word = "год"
    elif 2 <= last <= 4 and penult != 1:
        word = "года"
    else:
        word = "лет" 
    
    print ("Вам %s %s" % (age, word))
    
    Возраст: 11
    Вам 11 лет
    
    Возраст: 101
    Вам 101 год
    

    Функции

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

    Объявление

    Как и переменная, функция должна быть объявлена перед использованием (вызовом). Для этого используется ключевое слово def.

    # функция для находения суммы трех чисел
    def sum_of_three(argument1, argument2, argument3):
        result = argument1 + argument2
        result = result + argument3
        
        return result
    
    Заметки зануды
    На самом деле, объявление — это только указание имени и аргументов функции, а описание тела функции — это определение. Но так как в питоне объявление и определение нераздельны, можно применять любой термин ;)
    • def — ключевое слово (от define) для обозначения начала объявления функции
    • sum_of_three — название функции. Подчиняется тем же правилам, что и названия переменных
    • (argument1, argument2, argument3) — определение аргументов — переменных, значения которых будут переданы в момент вызова. Количество аргументов неограниченно, их даже может не быть вообще.
    • тело функции — любые операции, обязательно с отступами у каждой строчки. это единственный способ для питона отличить тело функции от остального кода программы.
    • return — ключевое слово, указывающее, какое значение должно быть возвращено как результат работы функции. Функция может не возвращать никакого значения.

    Вариации.

    Без аргументов.

    # функция чтения целого числа из консоли
    def get_integer_from_console():
        string_value = input("Enter any number: ")
        integer_value = int(string_value)
        return integer_value
    

    Без возвращаемого значения.

    # функция, выводящая в консоль полное имя человека
    def print_full_name(first_name, last_name):
        full_name = first_name + " " + last_name
        print(full_name)
    

    Вызов

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

    funciton_name(1, "value", variable)

    Если функция возвращает какое-то значение, оно может быть записано в переменную или использовано в любой операции

    Количество передаваемых в функцию значений должно строго соответствовать количеству аргументов в объявлении функции.
    Например, объявленная выше функция sum_of_three(argument1, argument2, argument3) принимает три аргумента. Мы можем вызвать ее так: sum_of_three(10, 123, 14), при этом значения будут присвоены в том порядке, в котором они переданы: argument1 = 10, argument2 = 123, argument3 = 14. Мы не можем вызывать функцию с иным количеством аргументов, чем в объявлении: sum_of_three(1, 2) или sum_of_three(1, 2, 3, 4) — приведет к ошибке.

    Примеры.

    # запишем результат выполнения функции в переменную
    sum1 = sum_of_three(1, 2, 3)
    print(sum1) 
    
    # передадим результат выполнения функции напрямую в функцию print
    print(sum_of_three(2, 3, 4)) выведет 9
    
    # используем результат выполнения функции в вычислении другого значения
    average = summ_of_three(10, 15, 20) / 3
    print(average) выведет 15
    
    # используем функцию, не принимающую аргументов
    # пустые скобки обязательны
    value = get_integer_from_console() 
    
    #используем функцию не возвращающую значения
    print_full_name("Anton", "Zemel")
    
    6
    9
    15
    Anton Zemel
    

    Назначение

    Функция позволяет неоднократно производить ОДНИ и те же действия с РАЗНЫМИ данными. Если искать параллели с реальным миром, то функцией можно назвать, например, определение ритмического рисунка стихотворной строки. Эта задача совсем не зависит от того, какую именно строку вы собираетесь анализировать (нужно лишь иметь информацию о слоговом составе этой строки). Если бы у нас был специальный человек, чьей работой было бы определение ритмического рисунка строк, то наше взаимодействие с ним выглядело бы следующим образом:

    1. Мы приносим ему строку (возможно, разбитую на слоги с проставленными ударениями)
    2. Он составляет ритмический рисунок строки, при этом мы не знаем, как он это делает и нас это не интересует.
    3. Мы возвращаемся к нему и получаем ритмический рисунок строки, например, в виде "--/--/--"
    Схема коммуникации с человеком-определителем-ритма никак не зависит от конкретной строки, которую мы хотим проанализировать.

    В питоне это выглядело бы так:

    def determine_rhythm(line):
        rhythm = ""
        # хитрый алгоритм определения ритмического рисунка
        return rhythm
    
    print(determine_rhythm("Душа мрачна, мечты мои унылы"))
    print(determine_rhythm("Грядущее рисуется темно."))
    # и т. д.
    
    -/-/-/-/-/-
    -/---/---/
    

    Использование функций дает следующие преимущества:

    1. Сокращает объем кода. Представьте, если бы мы повторяли весь алгоритм определения ритмического рисунка для каждой строки Евгения Онегина

    2. Делает код более организованным и понятным. Разбиение всей программы на подпрограммы позволяет лучше понимать ее, двигаясь от общего к частному или наоборот.

      numbers = read_numbers()
      average = find_average(numbers)
      print("Average is " + average)
      

      Даже не зная, как именно работают функции read_numbers и find_average, вы, тем не менее, можете понять, что делает эта программа в целом.

    3. Облегчает изменения и улучшения кода. Предположим, вначале у нас работал [непрофессиональный] человек, который определял ритм без учета клитиков, а потом мы придумали другого, который их учитывает. При этом наша схема коммуникации с ним не изменилась, мы так же даем ему строку стихотворения и получаем ритмический рисунок. По аналогии, в коде изменится определение функции в одном единственном месте, а весь остальной код останется нетронутым.

      def determine_rhythm(line):
          rhythm = ""
          # БОЛЕЕ хитрый алгоритм определения ритмического рисунка. Изменения здесь
          return rhythm
      
      # вызовы остались без изменений
      print(determine_rhythm("Душа мрачна, мечты мои унылы"))
      print(determine_rhythm("Грядущее рисуется темно."))
      # и т.д.
      
    4. Позволяет удобно использовать код, написанный другими людьми, не вникая в то, КАК он работает, лишь зная, ЧТО он делает и зная коммуникативную схему — интерфейс. Например, мы уже использовали некоторые встроенные функции питона: print — для вывода в консоль, input — для чтения из консоли, int, bool, str, float — функции для преобразования типов данных. Мы не знаем, как они работают, но все равно успешно их используем.

    Сравните два решения задачи согласования числительного и существительного с и без использования функций.

    Грядущее

    • Работа со строками
    • Перечисляемые типы данных
    • Циклы
    • Регулярные выражения
    • Работа с файлами
    • Основы ООП
    • Модули и пакеты
    • Использование библиотек
    • ...