Определение и вызов функций: ключевые аспекты
Основы определения функции
Наиболее распространённый способ создания функции в 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