У меня есть некоторые функции, которые при нормальных обстоятельствах вызываются с аргументами, предоставленными пользователем. Однако справедливо назвать некоторые из этих функций некоторыми рядами аргументов, которые определяются во время выполнения на основе некоторого состояния системы.Декоратор, который условно активирует другой декоратор?
Я хочу, чтобы у пользователя был , а необязательно поручил моей программе вызывать эти функции со всеми действительными вводами и возвращать результаты каждого вызова. Я думаю, что декоратор, который будет работать как активационный переключатель для функций, которые имеют другой декоратор, который указывает, какая серия аргументов для использования будет работать хорошо.
Кроме того, I требуется для сохранения сигнатуры функции и метаданных. Это жизненно важно для работы моей программы.
Это то, что я пробовал, но он не работает. Он основан на this example.
>>> from decorator import decorator
>>> def the_list():
... return ["foo", "bar", "baz"]
...
>>> import itertools
>>> @decorator
... def do_all(func):
... # this will do nothing (besides wrap in a tuple) unless func is decorated with @gets_arg_from
... if hasattr(func, 'get_from'):
... return tuple(func(*args) for args in itertools.product(*(list_fun() for list_fun in func.get_from)))
... else:
... return (func(),)
...
>>> def gets_arg_from(*list_funcs):
... # this will do nothing to func unless decorated with @do_all
... def gets_arg_from(func, *args, **kwargs):
... func.get_from = list_funcs
... return func(*args, **kwargs)
... return decorator(gets_arg_from)
...
>>> @gets_arg_from(the_list)
... def print_func(word):
... # this will print its argument unless decorated with @do_all
... # at that point it will print every element returned by the_list()
... print word
...
>>> print_func("foo")
foo
>>> all = decorator(do_all, print_func)
>>> all()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: print_func() takes exactly 1 argument (0 given)
>>> print_func.get_from
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'function' object has no attribute 'get_from'
Что я ожидал был:
>>> all()
("foo", "bar", "baz")
То, что я заметил, это не так:
gets_arg_from
не добавляет атрибутget_from
кfunc
.- Кое-что обо мне, используя обозначение
@gets_arg_from(the_list)
не так. Он думает, что я пытаюсь передать два аргумента (но почему это будет проблема так или иначе?)
Что касается моей мотивации, я думаю, декораторов для этого, потому что есть буквально сотни этих процедур, их детали реализации (а также их функциональная корректность) подвержены частым изменениям, и я не хочу использовать inspect
, чтобы рассуждать о том, что делать на основе их имен аргументов, и я не хочу жестко кодировать функциональность do_all
для каждой функции для что имеет смысл. Методы класса могут работать, но для моей цели они семантически надуманны. Кроме того, ради других, которым, возможно, придется поддерживать мой код, я думаю, что проще попросить их применить декоратор и не беспокоиться об остальном, а не использовать определенные имена аргументов или разместить функцию в определенном классе или без разницы. Я понимаю, что этот вопрос может показаться странным, поэтому я решил, что эта сноска может помочь мне выглядеть меньше, чем сумасшедший.
Что вы на самом деле делаете? Это похоже на модульное тестирование. Вы единичное тестирование? – user2357112
@ user2357112 Нет, я не знаю. Я пытаюсь сделать своего рода «переключатель» для функций, которые имеют определенные свойства (т. Е. Определенный тип декоратора). – 2rs2ts
Я не уверен, что я слежу за 100%, но моя первоначальная мысль заключалась в том, что вы можете работать с 'functools.partial' здесь ...? –