Как преобразовать объект одного класса в класс другого объекта,

Есть задумка сделать функцию, которая будет сверять, можно ли конвертировать объект в нужный класс. Вот код:

class func:
    function_list = []

def add_function(name: str, args_types: list):
    func.function_list.append((name,args_types))


def chech_function(name: str, args: list):
    for function in func.function_list:
        if function[0] == name:
            if len(function[1]) == len(args):
                try:
                    i = 0
                    while i < len(function[1]):
                        args[i].__class__ = function[1][i]
                        i+=1
                    return True
                except:
                    return False
                    

add_function("Test1",[str,int])
chech_function("Test1",["2",1])

Однако при запуске, он всегда выдает "False". Что я сделал не правильно?


Ответы (1 шт):

Автор решения: Vladimir Bogdanov

Ниже код, близкий по духу вашему. Советую почитать про модуль inspect. Там много чего интересного.

def type_checking(*type_args, **type_kwargs):
    """Декоратор, позволяющий выполнять проверку типов аргументов, передаваемых в функцию.
    Требование проверки типов можно задавать как для всех аргументов, так и выборочно.
    Требуемые типы сопоставляются с аргументами либо попозиционно, либо как ключ-значение.
    Требуемый тип задается либо как отдельное значение, либо как кортеж типов.

    Examples:
        >>>
        @type_checking(int, (int, str), z=float)
        def somefunction(x, y, z=4.5):
            pass
        # Альтернативный вариант
        @type_checking(y = (int, str), x = int)
        def somefunction(x, y, z=4.5):
            pass
        # Результат работы декоратора
        somefunction(1, 3, z=123.5)   #OK
        somefunction(1, '3', z=123.5)   #OK
        somefunction(1, 3)   #OK
        somefunction('1', 3, z=123.5)   #Error
        somefunction(1, 3, z=123)   #Error for first variant
        somefunction(1, 3.4)   #Error
    """

    def decorate(func):
        # В режиме оптимизации отключаем декоратор
        if not __debug__:
            return func
        # Формируем словарь, связывающий арнументы функции с требованиями типов, заданными в декораторе
        func_signature: inspect.Signature = inspect.signature(func)
        args_types: OrderedDict[str, Any] = func_signature.bind_partial(
            *type_args, **type_kwargs
        ).arguments

        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            # Формируем словарь с именами преданных функции аргументов и их значениями
            for arg_name, arg_value in func_signature.bind(
                *args, **kwargs
            ).arguments.items():
                # Если для данного аргумента задана проверка типа
                if arg_name in args_types:
                    # Если тип значения аргумента не соответствует заданному в декораторе
                    if not isinstance(arg_value, arg_types := args_types[arg_name]):
                        # Для join нужен кортеж
                        arg_types = (
                            arg_types
                            if isinstance(arg_types, Iterable)
                            else (arg_types,)
                        )
                        # Собираем строку вида 'typename or typename ...'
                        arg_type = " or ".join(
                            # Если '__name__' отсутствует, класс типа возвращает сам себя
                            str(getattr(arg_type, "__name__", arg_type))
                            for arg_type in arg_types
                        )
                        raise TypeError(f"Argument '{arg_name}' must be {arg_type}")
            # Проверка типов пройдена успешно. Вызываем оригинальную функцию
            return func(*args, **kwargs)

        return wrapper

    return decorate
→ Ссылка