通常の状況では、ユーザー入力によって提供される引数で呼び出される関数がいくつかあります。ただし、一部のシステム状態に基づいて実行時に決定される特定の一連の引数を使用して、これらの関数の一部を呼び出すことは有効です。
ユーザーがオプションで、すべての有効な入力でこれらの関数を呼び出し、各呼び出しの結果を返すようにプログラムに指示できるようにしたいと考えています。使用する一連の引数を示す別のデコレータを持つ関数のアクティベーションスイッチのように機能するデコレータがうまく機能すると思います。
さらに、関数のシグネチャとメタデータを保持する必要があります。それは私のプログラムの操作に不可欠です。
これは私が試したものですが、うまくいきません。この例に基づいています。
>>> 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)
が間違っています。2 つの引数を渡そうとしていると思われます (しかし、なぜそれが問題になるのでしょうか?)
私の動機としては、これらのルーチンが文字通り何百もあり、それらの実装の詳細 (および機能の正確さ) が頻繁に変更される可能性があるため、デコレータについて考えてinspect
います。引数名に基づいて、do_all
意味のある各関数の機能をハードコーディングしたくありません。クラス メソッドは機能するかもしれませんが、私の目的では、それらは意味論的に工夫されています。さらに、私のコードを維持しなければならない可能性のある他の人のために、特定の引数名を使用したり、特定のクラスに関数を配置したりするよりも、デコレーターを適用して残りを気にしないように依頼する方が簡単だと思います。なんでもいい。この質問は奇妙に聞こえるかもしれませんが、この脚注が私を狂人のように見せるのに役立つかもしれないと考えました.