2016-06-24 6 views
2

私は多くの関数を持つpythonモジュールを持っており、それらのすべてにデコレータを適用したい。 デコレータを適用する行にコピー貼り付けをしなくても、すべての機能にこのデコレータを適用するために、サルパッチを使用してすべてをパッチする方法はありますか?言い換えればデコレータでモジュール内のすべての関数にパッチを当てる

、私はこの置き換えたい:これにより

@logging_decorator(args) 
func_1(): 
    pass 

@logging_decorator(args) 
func_2(): 
    pass 

@logging_decorator(args) 
func_3(): 
    pass 


@logging_decorator(args) 
func_n(): 
    pass 

を:

patch_func(): 
    # get all functions of this module 
    # apply @logging_decorator to all (or not all) of them 

func_1(): 
    pass 

func_2(): 
    pass 

func_3(): 
    pass 

func_n(): 
    pass 
+3

私はあなたがそれをどうやって行うのかは分かりませんが、私はあなたがすべきではないと思います。明示的にする方が良いです。検索/置換は、すべての関数にタイプする必要があるという問題を解決するのに役立ちます。 –

+2

終わりではありませんが、 'import'すると、モジュールが公開している名前を反復してそこからパッチを当てることができます。 – jonrsharpe

+3

[this](http://code.activestate.com/recipes/577742-apply-decorators-to-all-functions-in-a-module/)を試しましたか?それは少し混乱しているようです。 – Jezor

答えて

3

私は本当にこれは良いアイデアであることは確かではありませんよ。結局、Explicit is better than implicit

これは、inspectを使用してモジュールのどのメンバーをデコレートできるかを調べ、__dict__を使用してモジュールのコンテンツを操作するというように機能します。

import inspect 

def decorate_module(module, decorator): 
    for name, member in inspect.getmembers(module): 
     if inspect.getmodule(member) == module and callable(member): 
      if member == decorate_module or member == decorator: 
       continue 
      module.__dict__[name] = decorator(member) 

使用例:

def simple_logger(f): 
    def wrapper(*args, **kwargs): 
     print("calling " + f.__name__) 
     f(*args, **kwargs) 
    return wrapper 

def do_something(): 
    pass 

decorate_module(sys.modules[__name__], simple_logger) 
do_something() 
+0

私は必要なものと非常に似ています!ここにデコレータの引数を渡す方法はありますか?実際に '@logging_decorator(args)'はこれらのトレースを追跡するためにargsをとるためです。 – Paul

+0

引数を持つデコレータは、その引数をラップする標準デコレータを返すように実装されています。したがって、 'decorate_module(module_to_wrap、logging_decorator(args)) 'を使うと便利です。私の現在のアプローチの限界は 'logging_decorator'があなたがラップしようとしているモジュールに存在するならば、' decorate_module'はそれを装飾しようとします。これは悪いかもしれません。 ( 'decorate_module'はデコレータをデコレートしようとしませんが、decorating-with-argumentsはその場で新しい関数を生成するので動作しません) –

+0

実際に私のロギングデコレータは他のpackgeにあります。問題。ありがとうございました! – Paul

1

私はつもりはかなりではないです...しかし、あなたはその定義の後にディレクトリを()を使用して、すべての機能を一覧表示することができます。それでラッパー関数なしでそれらをパッチする方法は考えられません。

def patched(func): 
    @logging_decorator 
    def newfunc(*args, **kwargs): 
     return func(*args, **kwargs) 
    return newfunc 

funcs=[f in dir() if not '__' in f] 
for f in funcs: 
    exec(f+'=patched(f)') 
関連する問題