Сопоставьте аргументы с inspect.signature.bind_partial, заполните отсутствующие именованные параметры из конфигурации и проверьте полный вызов через bind.
Декоратор, подставляющий недостающие параметры функции
Сопоставьте аргументы с inspect.signature.bind_partial, заполните отсутствующие именованные параметры из конфигурации и проверьте полный вызов через bind.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Создайте декоратор, который позволяет вызывать любую функцию, даже если при вызове переданы не все её параметры. В случае отсутствия некоторых аргументов декоратор должен подменять их заранее определёнными значениями.
Ответ
Сопоставьте аргументы с inspect.signature.bind_partial, заполните отсутствующие именованные параметры из конфигурации и проверьте полный вызов через bind.
import inspect
from functools import wraps
def supply_defaults(**defaults):
def decorate(func):
signature = inspect.signature(func)
for name in defaults:
parameter = signature.parameters.get(name)
if parameter is None or parameter.kind in (
inspect.Parameter.VAR_POSITIONAL, inspect.Parameter.VAR_KEYWORD
):
raise ValueError(f'Неподходящий параметр: {name}')
@wraps(func)
def wrapper(*args, **kwargs):
bound = signature.bind_partial(*args, **kwargs)
for name, value in defaults.items():
bound.arguments.setdefault(name, value)
bound.apply_defaults()
signature.bind(*bound.args, **bound.kwargs)
return func(*bound.args, **bound.kwargs)
return wrapper
return decorate
Явно переданные значения, включая None, сохраняются. Неописанные обязательные параметры по-прежнему вызывают TypeError. Переданные изменяемые defaults разделяются между вызовами; для независимых объектов нужен контракт фабрик значений.