Как преобразовать объект одного класса в класс другого объекта,
Есть задумка сделать функцию, которая будет сверять, можно ли конвертировать объект в нужный класс. Вот код:
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