← Назад к вопросам
Когда создается объект функции в Python?
1.7 Middle🔥 201 комментариев
#DevOps и инфраструктура
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Когда создается объект функции в Python
Одно из ключевых понимаемых моментов — функции в Python это объекты первого класса. Важно знать точный момент их создания и жизненный цикл.
Момент создания функции
Объект функции создается при выполнении оператора def, а не при вызове функции.
Демонстрация
# Функция создается при выполнении этой строки
def my_function():
print("Hello")
print(f"Функция создана: {my_function}")
print(f"Тип: {type(my_function)}")
print(f"ID объекта: {id(my_function)}")
# Вызов функции НЕ создает новый объект
my_function() # Просто вызывает существующий объект
print(f"ID после вызова: {id(my_function)}") # Тот же ID!
Вывод:
Функция создана: <function my_function at 0x7f...>
Тип: <class 'function'>
ID объекта: 140188...
ID после вызова: 140188... # Тот же!
Подробный жизненный цикл
1. Время загрузки модуля (load-time)
# file.py
print("Start module loading")
def func1():
print("func1 called")
print("Function created")
# Результат при импорте:
# Start module loading
# Function created
# (func1 ещё не вызывалась!)
2. Время вызова (runtime)
def func1():
print("func1 called")
# Объект функции существует
print(type(func1)) # <class 'function'>
# Вызов функции выполняет её тело
func1() # Вывод: "func1 called"
Функции как объекты
# Функция создается при def
def greet(name):
return f"Hello, {name}!"
# Это объект с атрибутами и методами
print(greet.__name__) # 'greet' — имя функции
print(greet.__doc__) # None — docstring
print(greet.__module__) # '__main__' — модуль
print(greet.__code__) # <code object> — байт-код
print(greet.__defaults__) # (None,) — значения по умолчанию
print(callable(greet)) # True — можно вызвать
# Функция может быть присвоена переменной
greeting = greet # Не создается новая функция, создается новая ссылка
print(greet is greeting) # True — это один и тот же объект
print(id(greet) == id(greeting)) # True
Время создания при разных сценариях
Сценарий 1: Глобальная функция
def outer():
print("Outer called")
# outer создана при выполнении строки def
# Даже если никогда её не вызвать, объект существует
Сценарий 2: Локальная функция (вложенная)
def outer():
# inner НЕ создается до вызова outer
def inner():
print("Inner called")
return inner
# inner ещё не создана!
fn = outer() # Теперь inner создана
fn() # Вызываем inner
Визуально:
def outer():
def inner(): # Создается при каждом вызове outer()
pass
return inner
inner1 = outer()
inner2 = outer()
print(inner1 is inner2) # False! Разные объекты
print(id(inner1) == id(inner2)) # False
Сценарий 3: Lambda функции
# Lambda создается в момент выполнения выражения
square = lambda x: x ** 2 # Объект создан здесь
print(type(square)) # <class 'function'>
# Каждое lambda выражение создает новый объект
fn1 = lambda x: x + 1
fn2 = lambda x: x + 1
print(fn1 is fn2) # False! Разные объекты, хотя код одинаков
Сценарий 4: Динамическое создание функции
# exec/eval создают функцию в runtime
code = """
def dynamic_func(x):
return x * 2
"""
namespace = {}
exec(code, namespace)
dynamic_func = namespace['dynamic_func']
print(dynamic_func(5)) # 10
print(type(dynamic_func)) # <class 'function'>
Когда НЕ создается новый объект
Присваивание переменной
def original():
pass
# copy НЕ является новым объектом
copy = original
print(original is copy) # True
print(id(original) == id(copy)) # True
Передача функции в качестве аргумента
def apply_function(func, value):
return func(value)
def add_one(x):
return x + 1
# add_one НЕ пересоздается, просто передается
result = apply_function(add_one, 5)
print(result) # 6
Время жизни функции
import sys
def func():
pass
# Счётчик ссылок
print(sys.getrefcount(func) - 1) # 2 (основная + аргумент getrefcount)
# Когда исчезают все ссылки, функция удаляется
func_ref = func
print(sys.getrefcount(func) - 1) # 3 (основная + func_ref + аргумент)
del func_ref
print(sys.getrefcount(func) - 1) # 2 (основная удалена)
Практические выводы
1. Декораторы создаются при def
def timer_decorator(func):
print(f"Decorating {func.__name__}") # Выведется при def
def wrapper(*args, **kwargs):
# Здесь выполняется логика
return func(*args, **kwargs)
return wrapper
@timer_decorator
def my_func():
pass
# Вывод: "Decorating my_func" (при определении, не при вызове)
my_func() # Только сейчас вызывается
2. Замыкания захватывают переменные
def make_multiplier(factor):
# Создается новая функция при каждом вызове
def multiplier(x):
return x * factor # factor захвачена в замыкание
return multiplier
mul2 = make_multiplier(2)
mul3 = make_multiplier(3)
print(mul2(5)) # 10
print(mul3(5)) # 15
print(mul2 is mul3) # False — разные объекты
3. Класс это тоже "функция"
class MyClass:
pass
# MyClass создается при выполнении class
print(type(MyClass)) # <class 'type'>
print(isinstance(MyClass, type)) # True
Ключевые моменты
- Функция создается при def — не при вызове
- Функция это объект — можно передавать, присваивать, проверять
- Вложенные функции — создаются при вызове внешней функции
- Каждое lambda — новый объект
- Декораторы выполняются при def — это важно для side effects
- Присваивание — не создает новый объект, только ссылку