Урок 9. Пользовательские функции


Продолжаем изучение Python и на очереди у нас такая интересная и достаточно сложная для начинающих программистов тема, как функции, а, точнее, пользовательские функции. Мы с Вами работали уже с функциями, использовали некоторые из них, например функция lеn, функция map. Len - универсальная функция, которая позволяет нам получить длину какой-то последовательности, это может быть строка, список. Эта функция, которая уже где-то там определена в Python. То есть, это встроенный в Python функция, которую нам предлагает данный язык программирования. Однако, как и любой другой язык программирования, Python позволяет нам создавать собственные функции. Для чего это может потребоваться? Функции нужны для того, чтобы избегать дублирования кода, чтобы многократно использовать тот или иной блок кода.

Чтобы объявить и вызвать функцию, нужно воспользоваться следующей конструкцией:

Объявление функции

def имя_функции(аргументы):
    тело функции
имя_функции(аргументы)  # вызов функции

Разберём следущие фукнкции

Функция 1

def hello():
    print("HELLO")

hello() # вызов функции
hello() # вызов функции
hello() # вызов функции

'''
Вывод
HELLO
HELLO
HELLO
'''

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

Функция 2

def introduction_and_hello(name, word):
    print("Hello " + name + ". Say " + word)


introduction_and_hello("John", "Hi")
introduction_and_hello("Katy", "Hello")
'''
Вывод:
Hello John
Hello Katy
'''

Функция 3

def get_sum(a, b):
    print(a + b)


get_sum(1, 3)
x = 1
y = 4
get_sum(x, y)
'''
Вывод:
4
5
'''

Можно создавать произвольное количество функций и бесконечно вызвать её.

Когда мы определяем нашу функцию, то хорошей практикой считается не печатать реузльтат работы функции, а возвращать его. Иногда вам нужно будет, чтобы функция только печатала, но в большинстве случаев вам нужно будет возвращать. Вы, возможно,будете делать промежуточные вычисления и будете использовать этот результат вне функции в дальнейших вычислениях. И сделать можно это с помощью инструкции return(возвращать). Чтобы посмотреть, что возвращает функция нужно воспользоваться функцией print().

Возвращаем элемент с помощью return

def get_multi(x, y):
    # в данном случае: x = 5, y = 6
    return x * y

a = 5
b = 6
print(get_multi(a, b))  # Вывод: 30
res = get_multi(a, b)  # возвращаемый результат также можно присваивать переменной и использовать в дальнейших вычислениях
print(res)  # Вывод: 30

Неявное - None

def check():
    print(2 + 3)
print(check())  # Вывод: None    Если мы не пишем return, то функция возвращает неявное, неявное это и есть None

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

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

Аргументы (параметры) функции

def get_sum_of(a, b, c, d):
    # Соответственно: a = x = 1,  b = y = 2, w = c = 3, d = z = 4;
    return a + b + c + d # возвращаем результат = 10

x = 1; y = 2; w = 3; z = 4
print(get_sum_of(x, y, w, z)) # передаём четыре аргумента. После вызова функции получаем результат = 10

Cейчас мы использовали 4 аргумента. Их может быть больше, может быть меньше. Но факт, что все эти аргументы являются обязательными и при том они являются, так называемыми, позиционными аргументами. Что будет, если я один аргумент не передам в функцию. Т.е, мы хотим передать в функцию 3 аргумента, но в описании функции принимаем всего 4. Давайте посмотрим, как это выглядит?

Позиционные элементы

def get_sum_of(a, b, c, d): # принимаем 4 элемента
    return a + b + c + d

x = 1; y = 2; w = 3;
print(get_sum_of(x, y, w)) # передаём три аргумента.

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

get_sum_of() missing 1 required positional argument: 'd'
Позиционные аргументы - это аргументы, которые при вызове функции, каждый из них, каждый из этих параметров соответствует позиции аргумента в описании функции.

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

Именнованные элементы

def get_sum_of(a, b, c=0, d=0): 
    return a + b + c + d # возвращает результат = 3, т.е   1 + 2 + 0 + 0 = 3

x = 1; y = 2;
print(get_sum_of(x, y)) # передаём 2 аргумента.

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

Именнованные аргументы должны стоять после позиционных аргументов.

Рассмотрим еще одну тему в данном уроке. Это произвольное количество аргументов, которое мы можем передать функции. До сих пор мы с вами использовали по сути заранее определённое количество аргументов. А что делать, если мы не хотим создать функцию, которая может принимать произвольное количество аргументов. Познакомимся на практике.

Как передать произвольное количество аргументов в функцию?

def get_tuple(*args):
    print(args)  # Вывод: (1, 2, 3)      # преобразован в кортеж(tuple).

def get_dict(**kwargs):
    print(kwargs)  # Вывод: {'a': 2, 'b': 4, 'c': 6}     # преобразован в словарь(dictionary).

get_tuple(1, 2, 3)   # вызов функции get_tuple()
get_dict(a = 2, b = 4, c=6)  # вызов функции get_dict()

Все те элементы, которые мы передадим под звёздочкой, они будут преобразованы в кортеж. Все те элементы, которые мы передадим под двумя звёздочками, будут преобразованы в словарь. В чём разница? Args - это позиционные аргументы. A kwargs(key word arguments) - это именованные аргументы. Вместо *args или **kwargs, мы можем написать другое имя, главное, чтобы звёздочки оставались на месте. Например: **array, *arr, *l, *list, **dict, **d и так далее.

Как одновременно передать список(*args) и словарь(**kwargs)

def get_all(r, m, *l, **d):
    print(r)  # Вывод: 1
    print(m)  # Вывод: 2
    print(l)  # Вывод: (5, 5, 5)     l = кортеж
    print(d)  # Вывод: {'a': 2, 'b': 4, 'c': 6}     d = словарь

get_all(1, 2, 5, 5, 5, a=2, b=4, c=6)   # вызов функции get_all()

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

Функция внутри функции

l = [1, 2, 3]
def func(l):
    def f2(x):
        return x * 2  # возвращает элемент, умножив его на 2.
    return [f2(i) for i in l]   # вызываем функцию f2, передав в качестве аргумента элементы списка L

print(func(l))  # вызываем функцию func, передав в качестве аргумента список L

# Вывод: [2, 4, 6]

Дан массив, в котором среди прочих элементов есть слово "odd". Определите, есть ли в списке число, которое является индексом элемента "odd". Напишите функцию, которая будет возвращать True или False, соответсвенно.

Решение

def odd_ball(arr):
    t = arr.index("odd")
    if t in arr:
        return True
    else:
        return False


print(odd_ball(['even', 4, "even", 7, "even", 55, "even", 6, "even", 10, "odd", 3, "even"]))  # True
print(odd_ball(['even', 4, "even", 7, "even", 55, "even", 6, "even", "odd", 3, "even"]))  # False
print(odd_ball(["even", 10, "odd", 2, "even"]))  # True

Напишите функцию find_sum(), где аргумент функции - это конечный элемент последовательности включительно. Функция должна вернуть сумму всех чисел последовательности, кратных 3 или 5. Попробуйте решить задачу двумя способами(одна из способов в одну строчку кода).

Решение

def find_sum(n):
    s = 0
    for i in range(1, n + 1):
        if i % 3 == 0 or i % 5 == 0:
            s += i
    return s


def find_sum1(n):
    return sum([i for i in range(n + 1) if i % 3 == 0 or i % 5 == 0])


print(find_sum(5))  # return 8
print(find_sum(10))  # return 33


print(find_sum1(5))  # return 8   
print(find_sum1(10))  # return 33


Дан список имён. Выберите в новый список только те имена, которые состоят из 4-х букв.

Решение

# 1 способ. решение в несколько строк
def get_names(names):
    a = []
    for i in names:
        if len(i) == 4:
            a.append(i)
    return a


names = ['Ryan', 'Kieran', 'Mark', 'John', 'David', 'Paul']
print(get_names(names))


# 2 способ. Решение в одну строку
def get_names(names):
    return [i for i in names if len(i) == 4]


names = ['Ryan', 'Kieran', 'Mark', 'John', 'David', 'Paul']
print(get_names(names))


Комментарии

Чтобы написать комментарии вам нужно войти в систему или зарегистрироваться