← Назад к вопросам

Когда создается объект функции в 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

Ключевые моменты

  1. Функция создается при def — не при вызове
  2. Функция это объект — можно передавать, присваивать, проверять
  3. Вложенные функции — создаются при вызове внешней функции
  4. Каждое lambda — новый объект
  5. Декораторы выполняются при def — это важно для side effects
  6. Присваивание — не создает новый объект, только ссылку
Когда создается объект функции в Python? | PrepBro