2

関数に適用するときにオプションの構成を可能にするデコレータを提供したいと思います。

簡単な実装は次のとおりです。

import functools


class Deco(object):
    config = {'message': 'hello'}

    def __init__(self, func):
         self.func = func
         functools.wraps(func)(self)

    def __call__(self, *args, **kwargs):
         print self.config['message']
         return self.func(*args, **kwargs)

    @classmethod
    def customize(cls, **kwargs):
         """Return a customized instance of this class. """
         return type(cls.__name__, (Deco, ), {'config': kwargs})


@Deco
def add(a, b): 
    return a + b 


@Deco.customize(message='bye')
def sub(a, b): 
    return a - b 


>>> add(1, 2)
'hello'
>>> sub(2, 1)
'bye'

これを使用して、Django ビューに使いやすいデコレータを提供したいと考えています。

このアプローチはエラーなしで機能しますが、クラスがそれ自体のカスタマイズされたインスタンスをインスタンス化する静的ファクトリ メソッドをデコレータとして持つことを許可することに何か問題がありますか?

4

1 に答える 1

2

デコレータが使用されるたびに追加のサブクラスを作成せずに作業できますが、コードは問題ありません。余分なサブクラスがない方法は、次のようなものになる可能性があります。

class Deco(object):
    config = {'message': 'hello'}

    def __init__(self, func=None, **kwargs):
         if kwargs:
             self.config = kwargs
         if func is not None:
             self._decorate(func)

    def _decorate(self, func):
        self.func = func
        functools.wraps(func)(self)

    def __call__(self, *args, **kwargs):
        if not hasattr(self, "func"):
            self._decorate(func)
            return self
        print self.config['message']
        return self.func(*args, **kwargs)

したがって、パフォーマンスに関しては、コードに違いはありません(少なくとも数十万の関数をデコレーションする場合を除いて、デコレータが使用されるたびに、そのインスタンスに加えて、コードが追加のオブジェクト(クラス)を作成します)クラス)-人々があなたのコードをレビューすることに影響があります(あなたのモジュールを使用するか、あなたが終わった後にそれを維持するために)。つまり、「それ自体のサブクラスを動的に生成するデコレータ」は、高度すぎるように聞こえ、人々を怖がらせる可能性があります。上記の私の提案と同じくらい簡単ですが、Pythonでのクラス生成のメカニズムを理解すると、あなたが持っていたようになります。

于 2012-10-17T20:15:03.750 に答える