Определение и вызов функций: ключевые аспекты

Раздел: Основы Python -> Базовые конструкции языка

Основы определения функции

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

def add(a, b):
    result = a + b
    return result

print(add(3, 5))  # 8

реализация функции в python (реализация функции в python)

Пояснение: Функция add принимает два параметра a и b, вычисляет сумму и возвращает её. При вызове add(3,5) аргументы передаются по позиции.

Типичная ошибка: Забыть написать return. В этом случае функция возвращает None.

def add(a, b):
    result = a + b
    # нет return

print(add(3, 5))  # None

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

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

def greet(name, age):
    return f"Привет, {name}! Тебе {age} лет."

print(greet("Анна", 25))  # Привет, Анна! Тебе 25 лет.

Проблема: Если передать меньше или больше аргументов, возникнет ошибка TypeError.

greet("Анна")  # TypeError: greet() missing 1 required positional argument: 'age'

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

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

def power(base, exponent=2):
    return base ** exponent

print(power(5))    # 25 (5^2)
print(power(5, 3)) # 125 (5^3)

Ошибка: Использование изменяемого объекта (список, словарь) в качестве значения по умолчанию. Этот объект создаётся один раз и разделяется между всеми вызовами.

def append_to(item, lst=[]):
    lst.append(item)
    return lst

print(append_to(1))  # [1]
print(append_to(2))  # [1, 2]  (ожидалось [2])

Решение: использовать None и создавать новый объект внутри функции.

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

Используются *args (кортеж позиционных аргументов) и **kwargs (словарь именованных аргументов).

def summarize(*args, **kwargs):
    print("Позиционные аргументы:", args)
    print("Именованные аргументы:", kwargs)

summarize(1, 2, 3, name="Python", version=3.12)
# Позиционные аргументы: (1, 2, 3)
# Именованные аргументы: {'name': 'Python', 'version': 3.12}

Проблема: Путаница в порядке объявления: *args должен идти после обычных параметров, а **kwargs - после *args. Иначе синтаксическая ошибка.

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

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

square = lambda x: x ** 2
print(square(4))  # 16

# Использование с filter()
nums = [1, 2, 3, 4, 5]
evens = list(filter(lambda x: x % 2 == 0, nums))
print(evens)  # [2, 4]

Ошибка: Попытка использовать сложные конструкции (циклы, if-elif-else) внутри lambda. Для этого нужно определить обычную функцию.

Зачем нужны функции внутри функций?

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

def outer(x):
    def inner(y):
        return x + y
    return inner

add_five = outer(5)
print(add_five(3))  # 8

Проблема: Если внутренняя функция ссылается на переменную внешней, необходимо использовать nonlocal для изменения этой переменной.

Как функция может вызывать саму себя?

Рекурсия - вызов функции из её же тела. Обязательно наличие базового случая для завершения.

def factorial(n):
    if n <= 1:
        return 1
    return n * factorial(n - 1)

print(factorial(5))  # 120

Ошибка: Отсутствие базового случая или неправильное условие приводит к бесконечной рекурсии и переполнению стека (RecursionError).

Декоратор для логирования

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

Пример
def logger(func):
    def wrapper(*args, **kwargs):
        print(f"Вызвана функция {func.__name__} с аргументами {args} {kwargs}")
        return func(*args, **kwargs)
    return wrapper

@logger
def multiply(x, y):
    return x * y

print(multiply(3, 4))
Вызвана функция multiply с аргументами (3, 4) {}
12

Замыкание (счётчик вызовов)

Внутренняя функция запоминает состояние внешней переменной. Используется для создания фабрик функций с состоянием.

Пример
def counter():
    count = 0
    def inc():
        nonlocal count
        count += 1
        return count
    return inc

c = counter()
print(c())  # 1
print(c())  # 2
print(c())  # 3
1
2
3

Функция как объект первого класса (передача в map)

Функции можно передавать в качестве аргументов другим функциям. Это основа функционального стиля программирования.

Пример
def square(x):
    return x ** 2

numbers = [1, 2, 3, 4]
squared = list(map(square, numbers))
print(squared)
[1, 4, 9, 16]

Аннотации типов и документация

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

Пример
def divide(a: float, b: float) -> float:
    """Делит a на b."""
    if b == 0:
        raise ValueError("Деление на ноль")
    return a / b

print(divide(10, 3))  # 3.3333333333333335
3.3333333333333335

Частичное применение с functools.partial

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

Пример
from functools import partial

def power(base, exponent):
    return base ** exponent

square = partial(power, exponent=2)
cube = partial(power, exponent=3)

print(square(5))  # 25
print(cube(5))    # 125
25
125

Реализация функции в Python - comments

En
реализация функции в python (python)