Введение в функции. Модули

Введение

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

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

  • Пример: нам нужно рассчитать заработную плату. Для написания программы нам нужно разбить задачу на подзадачи:

1. Получение почасовой ставки оплаты труда сотрудника
2. Получение числа отработанных часов
3. Расчёт заработной платы сотрудника до удержаний
4. Расчёт оплаты сверхурочных часов
5. Расчёт налоговых и прочих удержаний
6. Расчёт чистой заработной платы
7. Печать ведомости на получение заработной платы
  • Мы видим список инструкций, выполняя которые по очереди мы добьемся цели

  • Мы можем выделить функцию для решения каждой подзадачи. В нашей программе могли бы быть такие функции:

- функция получения почасовой ставки оплаты труда сотрудника
- функция получения количества часов
- функция расчета заработной платы сотрудника до удержаний
- функция расчета оплаты сверхурочных часов
- функция расчета налоговых и прочих удержаний
- функция расчета чистой заработной платы
- функция печати ведомости на получение заработной платы
  • Это называется модульным подходом и модуляризацией программы

  • Какие преимущества такого подхода?

    • Более простой код. Каждую функцию читать легче, чем одну длинную последовательность

    • Повторное использование кода — уменьшение дублирования в программе

    • Более простое тестирование

    • Более быстрая разработка: написанные однажды функции могут быть применены в нескольких программах

    • Упрощение командной работы

Возврат значения

  • функции без возврата значения просто выполняют инструкции и ничего не возвращают

  • функции с возвратом значения что-то возвращают в ту инструкцию, которая её вызвала Примеры:

  • функция input() возвращает значение — строку

  • функции int() и float() тоже возвращают значение

  • функция print() ничего не возвращает, а только выполняет инструкцию печати

Функции без возврата значения

  • Именование:

    • имя функции должно отражать то, что она делает

    • не должно быть пробелов, ключевых слов Python

    • первый символ — буква или нижнее подчеркивание

    • как правило в именах функции используются глаголы ("get, take, calculate, print и т.д")

  • Синтаксис написания функций следующий

def имя_функции(): # это заголовок функции
    инструкция # это блок инструкций
    инструкция
    ...
  • Это называется определением функции. Говорят, что функция определена.

def message():
    print("Я - Артур,")
    print('король британцев')
  • Теперь вызовем функцию:

message()
  • Интерпретатор идет сверху вниз:

  1. Видит определение функции,

  2. Далее видит вызов функции,

  3. Возвращается к определению,

  4. Выполняет блок инструкций

  5. И затем снова возвращается к месту вызова.

  • Добавим ещё одну функцию в наш пример

# определяем главную функцию
def main():
    print("У меня для вас известие.")
    message()
    print("До свидания!")

# затем определяем функцию message
def message():
    print("Я - Артур,")
    print('король британцев')

# вызываем главную функцию
main()

Интерактив:

  • Из каких двух частей состоит определение функции?

  • Что значит "вызвать функцию"?

  • Зачем нужны отступы в блоке инструкций?

Разбор:

Напишем программу, которая выводит на экран инструкции по разборке
сушилки для белья фирмы Nika.
Чтобы разобрать сушилку, нужно:
1. Отключить сушилку и отодвинуть от стены
2. Удалить шесть винтов с задней стороны сушилки
3. Удалить заднюю панель сушилки
4. Вынуть верхний блок сушилки
Программа должна показывать шаг за шагом по очереди по нажатию клавиши
Enter. Также необходимо предусмотреть приветственное сообщение.
  • Подготовим "каркас нашей программы". Затем реализуем каждую функцию.

def main():
    '''
    Последовательно вызывает функции и печатает одну за другой.
    После каждой инструкции нужно нажать Enter, чтобы перейти к следующей.
    '''
    pass # инструкция-пустышка - можно использовать при проектировании
# сначала можно продумать функции, а потом написать блоки инструкций в них

def startup_message():
    '''
    Печатает приветственное сообщение
    '''
    pass 

def step1():
    pass
def step2():
    pass
def step3():
    pass
def step4():
    pass
  • Напишите программу. "Точкой входа" должна быть функция main().

Области видимости: локальная и глобальная;

  • Когда переменной внутри функции присваивается значение, создаётся локальная переменная. Инструкции за пределами функции не имеют к ней доступа. Говорят, что переменная доступна в локальной области видимости

  • Когда переменная создается снаружи функции, она является глобальной и доступна в глобальной области видимости

name = "Tatyana" # глобальная переменная
def print_name():
    print(name)
    
def print_another_name():
    name = "Sergey" # локальная переменная
    print(name)
    
print_name()
print_another_name()

def print_name_again():
    name = "Ilona"
    print(name)

print_name_again()
print(name)
  • Практика: напишите любую программу с применением глобальной и локальной переменных.

Передача аргументов в функцию

  • Аргумент — любая порция данных, передаваемая в функцию, когда она вызывается

  • Параметр — переменная, которая получает аргумент, переданный в функцию

def show_double(number): # number - параметр функции
    result = number * 2
    print(result)
  • Закончим программу и разберём каждый её шаг:

def main(): # определение функции main
    value = 5 # создание переменной value
    show_double(value) # вызов функции show_double с аргументом 5
    
def show_double(number): # определение функции show_double с параметром number
    result = number * 2 # создание переменной result
    print(result) # печать переменной result

main() # вызов функции main
  • Передавать можно несколько аргументов:

def main():
    print('Сумма чисел 12 и 45 равняется')
    show_sum(12, 45)
    
def show_sum(num1, num2):
    result = num1 + num2
    print(result)
    
main()
  • Напишите функцию, которая принимает имя и фамилию, и печатает на экран фамилию и имя (именно в этом порядке)

Именованные аргументы

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

def main():
    paral_volume(width=6, length=5, height=7)
    
def paral_volume(length, width, height):
    v = length * width * height
    print(f'Объём параллелепипеда с длиной {length}, шириной {width} и высотой {height} составит {v}')

main()
  • Можно смешивать именованные и позиционные аргументы

  • Важно соблюдать порядок — сначала позиционные, потом именованные аргументы

paral_volume(5, height=7, width=6)

Функции с возвратом значения

  • Функции могут не просто выполнять действие, но и возвращать результат

  • Для этого используется ключевое слово return. Значение, указанное после return, отправляется к месту вызова функции

def sum(num1, num2):
    result = num1 + num2
    return result
    
def hello(name, surname):
    return f'Hello, {name} {surname}'!
  • Напишем программу, которая спрашивает пользователя доходы за месяц и расходы за месяц. В результате она должна сообщить баланс по итогам месяца

Разбор
def main():
    plus_money = int(input('Введите доходы за месяц: '))
    minus_money = int(input('Введите расходы за месяц: '))
    balance = diff(plus_money, minus_money)    
    print(balance)
    
def diff(n1, n2):
    result = n1 - n2
    return result

main()

Возвращение булевых значений

def is_even(number):
    if number % 2 == 0:
        return True
    else:
        return False

def main():
    number = int(input('Введите число: '))
    if is_even(number): # вызов функции в качестве условия - т.к. она вернет булево значение
        print('Число четное')
    else:
        print('Число нечетное')

Интерактив:

def do_something(number):
    return number * 2
  • Как называется функция?

  • Что функция делает?

  • Что покажет приведенная ниже инструкция с учетом определения функции?

print(do_something(10))

Модули

  • Модуль — это файл, который содержит программный код Python. Большие программы легче отлаживать и поддерживать, когда они разделены на модули

  • Разделение, как правило, проводится по смыслу и логике — в одном модуле мы объединяем функции, выполняющие задачи в одной области

  • В стандартной библиотеке Python есть большое количество модулей, которые можно подключить при помощи инструкции import. Рассмотрим примеры использования одного из популярных модулей: random

import random
# from random import randint - способ импорта конкретной функции из модуля
# тогда эту функцию можно будет вызывать без названия модуля
# вот так: randint(0, 10)
random.randint(0, 10) # функция возвращает целое число в диапазоне от 0 до 10 включительно
random.randrange(start, stop, step) # возвращает случайно выбранное число из последовательности
lst = list(range(10)) # список целых чисел от 0 до 9
random.choice(lst) # вернет случайный элемент последовательности
random.shuffle(lst) # перемешает случайным образом элементы изменяемой последовательности
  • Практика: познакомьтесь с возможностями модуля math. Решите задачу поиска длины гипотенузы, зная длины катетов прямоугольного треугольника при помощи модуля math.

Импорт самописных модулей

  • Когда мы импортируем один модуль в другой, то выполняются инструкции этого модуля: определяются функции и переменные

  • Если в модуле вызывается какая-то функция, то при импорте этого модуля, она тоже будет вызвана

  • Чтобы избежать этого, используется следующая конструкция:

# определена какая-то функция main
def main():
    pass
    
# нам нужно, чтобы она вызывалась только если мы запускаем этот модуль
# а если этот модуль импортируется -- тогда на вызывалась
# используем такую конструкцию:    
if __name__ == '__main__':
    main()

Почему так происходит?

  • При обработке модуля интерпретатор создаёт переменную __name__

  • Если модуль импортируется, она равна имени модуля.

  • Если модуль запускается, она равна __main__

  • Таким образом, условие if __name__ == '__main__': выполнится только в случае, если модуль запускается непосредственно

Практика:

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

  2. Теперь импортируйте один модуль в другой. Запустите каждый модуль — понаблюдайте за результатом. Попробуйте добавить обратный импорт. Удалите вызов функции в одном модуле, потом в другом. Запускайте модули на каждом этапе.

  3. Добавьте конструкцию "if __name__ = '__main__':" в каждый модуль по очереди, проделайте шаги из пункта 2

  4. Обсудите результаты с преподавателем

Итог:

Всегда используйте конструкцию if __name__ == '__main__': в запускаемом (главном) модуле вашей программы


Интерактив:

  • Какое ключевое слово игнорируется интерпретатором и может использоваться в качестве местозаполнителя для кода, который будет написан позже?

  • Как определить функцию? Как её вызвать?

  • Глобальная или локальная переменная создаётся внутри функции?

  • Какая инструкция должна быть в функции для возврата значения?

  • Что такое булева функция?

  • Зачем разбивать большую программу на модули?

Last updated