Функции пользователя#

Создание функции#

asda

Фунцкция создается с помощью ключевого слова def.

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

Определение функции#

def say_hello():
        print("Hello, World!")

Вызов функции#

say_hello()

Инструкция return#

return используется в теле функции, если нужно вернуть какое-то значение. Если инструкции return нет, тогда по умолчанию функция будет возвращать объект None.

def my_function():
        pass
result = my_function()
result == None
True

Или как в этом примере:

# Определение функции
def sum_numbers(a,b):
        sum = a + b

print(sum_numbers(1,2))

None

Добавление return

# Определение функции
def sum_numbers(a,b):
        sum = a + b
        return sum

print(f'Сумма чисел равна {sum_numbers(1,2)}')

Сумма чисел равна 3

Attention

Функция выполняется до первого return. Инструкции, описанные после return, не выполняются.

# Определение функции
def sum_numbers(a,b):
        sum = a + b
        return sum
        print('Функция выполнена!!!\n')

print(f'Сумма чисел равна {sum_numbers(1,2)}')

Сумма чисел равна 3

# Определение функции
def sum_numbers(a,b):
        sum = a + b
        print('Функция выполнена!!!\n')
        return sum

print(f'Сумма чисел равна {sum_numbers(1,2)}')

Функция выполнена!!!
Сумма чисел равна 3

Возврат нескольких значений#

Если после оператора return указать несколько значений, то они будут возвращены в точку вызова функции в виде кортежа:

# Определение функции
def sum_numbers(a,b):
        sum = a + b
        return a, b, sum

result = sum_numbers(5,7)

print(result)

(5, 7, 12)

Пример: Високосный год#

Написать скрипт для определения “високосности” года. Год является високосным, если его значение кратно 4 и не кратно 100 или кратно 400

def is_leap_year(year):
        if (year % 4 == 0 and year % 100 != 0) or year % 400 == 0:
          return True
        else:
          return False

# Ввод данных
my_year = int(input('Введите год: '))

# Функция вызывается и её результат проверяется if
if is_leap_year(my_year):
        print(f'{my_year} - високосный год')
else:
        print(f'{my_year} - не високосный год')

Введите год: 2023
2023 - не високосный год

После ввода номер года, он записывается в переменную my_year. Далее, эта переменная в качестве аргумента передается функции is_leap_year и там записывается в параметр year. Это значение проверяется в функции в операторе if. В зависимости от истинности этого условия в точку вызова программы возвращается результат. И на основании этого результата уже в основной функции печатается в консоль результат проверки.

Более лаконичный вариант функции:

def is_leap_year(year):
        return (year % 4 == 0 and year % 100 != 0) or year % 400 == 0

Документация (docstring)#

Первая строка в определении функции - это docstring, строка документации. Это комментарий, который используется как описание функции:

def is_leap_year(year):
        """
        Функция определения високосности года
        """
        return (year % 4 == 0 and year % 100 != 0) or year % 400 == 0

is_leap_year?

is_leap_year.__doc__

'\n    Функция определения високосности года\n    '

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

Параметры функции#

Параметры функции бывают: - Обязательные; - Необязательные (опциональные, со значением по умолчанию).

Обязательные параметры#

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

def print_names(name1, name2):
        print(name1)
        print(name2)

print_names('Михаил','Валентина')

Михаил
Валентина

print_names('Зоя')

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[23], line 1
----> 1 print_names('Зоя')

В данном случае фунция ожидает 2 аргумента, а ей передан один.

Необязательные параметры (параметры со значением по умолчанию)#

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

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

def check_passwd(username, password, min_length=8):
        """
        Функция проверки ппароля на соответствие требованиям, устанавливаемым к паролям
        """
        if len(password) < min_length:
                print('Пароль слишком короткий')
                return False
        elif username in password:
                print('Пароль содержит имя пользователя')
                return False
        else:
                print(f'Пароль для пользователя {username} прошел все проверки')
                return True

# Вызов функции без указания min_lendth
check_passwd('mike', '2345')

Пароль слишком короткий

False

При работе функции было подставлен значение min_length, равное 8, как в определении функции

# Вызов функции с указанием min_lendth
check_passwd('mike', '2345', 3)

Пароль для пользователя mike прошел все проверки

True

При работе функции c таким набором параметров было подставлено значение min_length, равное 3.

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

Аргументы функции#

Аргументы функции бывают:

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

  • Ключевые - передаются с указанием имени аргумента и его значения. Так как их имя указывается явно, то таком случае, аргументы могут быть указаны в любом порядке.

asda

При вызове функции с испльзованием и позиционных и ключевых агрументов первыми передаются позиционные

    # Вызов функции с указанием ключевого аргумента после позиционных
    check_passwd('mike', '2345', min_length=3)

    Пароль для пользователя mike прошел все проверки
    True

    # Вызов функции с указанием ключевого аргумента перед позиционными
    check_passwd(min_length=3, 'mike', '2345')

    Cell In[28], line 2
check_passwd(min_length=3, 'mike', '2345')
                                         ^
    SyntaxError: positional argument follows keyword argument

Позиционные аргументы#

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

def print_names(name1, name2):
        print(name1)
        print(name2)

print_names('Михаил','Валентина')

Михаил
Валентина

print_names('Валентина','Михаил')

Валентина
Михаил

Attention

Количество аргументов должно совпадать с количеством параметров:

print_names('Зоя')

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[32], line 1
----> 1 print_names('Зоя')

TypeError: print_names() missing 1 required positional argument: 'name2'

Attention

Порядок важен, так как нарушается логика работы программного кода внутри функции

def calculate_fraction(x, y):
        return x/(1-y)

calculate_fraction(1,2)

-1.0

calculate_fraction(2,1)

---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
Cell In[35], line 1
----> 1 calculate_fraction(2,1)

Cell In[33], line 2, in calculate_fraction(x, y)
          1 def calculate_fraction(x, y):
----> 2     return x/(1-y)

ZeroDivisionError: division by zero

Во втором случае значение 1 записалось в переменную y и при подстановке в дробь олучился 0, а на 0 делить нельзя -> ошибка.

Произвольное количество позиционных аргументов, *args#

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

Обычно данный параметр записывают ** args*

*args - ожидает аргументы переменной длины (при каждом вызове могут быть разными)

def accept_patients(doctor, *args):
        print(f'Список пациентов для доктора {doctor}:')
        print('-'*20)
        for el in args:
                print(el)

accept_patients("Пархоменко","Васильев", "Петрова", "Лопатин")

Список пациентов для доктора Пархоменко:
--------------------
Васильев
Петрова
Лопатин
accept_patients("Николаев","Иванов", "Слепов", "Вакутагин","Кошкин")

Список пациентов для доктора Николаев:
--------------------
Иванов
Слепов
Вакутагин
Кошкин
def accept_patients(*args,doctor):
        print(f'Список пациентов для доктора {doctor}:')
        print('-'*20)
        for el in args:
                print(el)

accept_patients("Пархоменко","Васильев", "Петрова", "Лопатин")

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[42], line 7
          4     for el in args:
          5         print(el)
----> 7 accept_patients("Пархоменко","Васильев", "Петрова", "Лопатин")

TypeError: accept_patients() missing 1 required keyword-only argument: 'doctor'

Python обрабатывает позиционные аргументы следующим образом:

подставляет обычные позиционные аргументы слева направо, а затем помещает остальные позиционные аргументы в кортеж (*args)

В приведенном примере все элементы были захвачены в args и на долю параметра doctor аргументов на хватило. Требуется явно указывать ключевой параметр doctor и передавать значения.

Передача только позиционных аргументов#

Если требуется передавать в функцию аргументы ТОЛЬКО как позиционные, то при определении функции после всех позиционных параметров требуется указать символ слэш /

def calculate_fraction(x, y,/):
        return x/(1-y)

calculate_fraction(1,2)

-1.0
calculate_fraction(1,y=2)

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[45], line 1
----> 1 calculate_fraction(1,y=2)

TypeError: calculate_fraction() got some positional-only arguments passed as keyword arguments: 'y'

Здесь ошибка возникла, потому что указано y=2 (ключевой аргумент), а это запрещено в определении функции.

Ключевые аргументы#

  • передаются с указанием имени аргумента;

  • могут передаваться в любом порядке

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

check_passwd(min_length=3, username='mike', password='2345')

Пароль для пользователя mike прошел все проверки
True

В приведенном примере все аргументы были переданы, как в ключевые.

Передача только ключевых аргументов#

Если требуется передавать в функцию аргументы ТОЛЬКО как КЮЧЕВЫЕ, то при определении функции после ПЕРЕД этими параметрами требуется указать символ звездочка *

def calculate_fraction(*,x, y):
        return x/(1-y)

Так вызвать уже нельзя

calculate_fraction(1,2)

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[49], line 1
----> 1 calculate_fraction(1,2)

TypeError: calculate_fraction() takes 0 positional arguments but 2 were given

Можно только так:

calculate_fraction(y=2,x=1)

-1.0

Произвольное количество аргументов-ключевых слов **kwargs#

Как и в случае с позиционными аргументами можно определять произвольное количество аргументов-ключевых. Параметр, который принимает ключевые аргументы переменной длины, создается добавлением перед именем параметра двух звездочек. Имя параметра может быть любым, чаще всего, используют имя <b>**kwargs</b> (от keyword arguments).

def sum_arg(a, **kwargs):
        print(a, kwargs)
        return a + sum(kwargs.values())

sum_arg(a=10, b=10, c=20, d=30)

10 {'b': 10, 'c': 20, 'd': 30}
70

Функция sum_arg создана с двумя параметрами:

  • параметр a (если передается как позиционный аргумент, должен идти первым, если передается как ключевой аргумент, то порядок не важен)

  • параметр **kwargs - ожидает ключевые аргументы переменной длины, куда попадут все остальные ключевые аргументы в виде словаря. Эти аргументы могут отсутствовать

sum_arg(a=10, b=10, c=20, d=30, k=12, e=-10)

10 {'b': 10, 'c': 20, 'd': 30, 'k': 12, 'e': -10}
72

sum_arg(10)

10 {}
10

Комбинация позиционных и ключевых элементов#

Можно комбинировать два типа аргументов в одной и той же функции.

Любой аргумент перед символом / предназначен только для позиционных аргументов, а любой аргумент после символа * - только для ключевых слов.

def my_function(a, b, /, *, c, d):
  print(a + b + c + d)


my_function(5, 6, c = 7, d = 8)

26
    my_function(5, c = 7, d = 8, 6)

    Cell In[59], line 1
my_function(5, c = 7, d = 8, 6)
                              ^
    SyntaxError: positional argument follows keyword argument

Ошибка: позиционный аргумент 6 записан после ключевых

Анонимная функция: лямбда#

Лямбда-функция — это короткая однострочная функция, которой не имеет имени.

Лямбда-функция может принимать любое количество аргументов, но может содержать только одно выражение.

Такие выражения содержат лишь одну инструкцию, поэтому, например, if, for и while использовать нельзя.

Синтаксис:

lambda arguments : expression

# Добавить значение 10 к аргументу и вернуть результат

x = lambda a : a + 10
print(x(5))

15

Функция является объектом, поэтому можно ее присвоить какой-нибудь переменной. В данном случае x. При вызове x c аргументом 5 данное значение записывается в параметр a и будет срабатывать иструкция 5 + 10. Возвращен результат 15.

# Перемножить аргументы a и b и вернуть результат

x = lambda a, b : a * b
print(x(5, 6))

30

Создать lambda-функцию, возвращающую первый и последний символ строки

f = lambda x: x[0] + x[-1]
print(f('Jupyter'))

Jr