1

@property のように機能するデコレータを作成しようとしていますが、いくつか問題が発生しています。

class Dec(object):
  def __init__(self, fn):
    self._fn = fn
    self._before = None
  @property
  def before(self)
    return self._before
  @before.setter
  def before(self, fn):
    self._before = fn
  def __call__(self, *args, **kwargs):
    self._before(*args, **kwargs)
    self._fn(*args, **kwargs)

def withbefore(fn):
  return Dec(fn)

単純なチェーン デコレータです。@property/@.setter 構文はまさに私が複製しようとしているものです。

これは機能します:

@withbefore
def foo():
   ...
@foo.before
def beforefoo():
  ...

しかし、クラスではそうではありません:

class Weee(object):
    @withbefore
    def do_stuff(self):
      pass
    @do_stuff.before
    def before_do_stuff(self):
      pass

インポートエラーが発生します。

TypeError: 'NoneType' object is not callable

@property/.{setter,getter,deleter} を正しくエミュレートするにはどうすればよいですか?

4

2 に答える 2

1

よろしくお願いします。

from functools import wraps

def withbefore(fn):
    def dec(bef):
        fn._before_fn = bef
        return bef

    @wraps(fn)
    def _wrapper(*args, **kwargs):
        fn._before_fn(*args, **kwargs)
        return fn(*args, **kwargs)

    _wrapper.before = dec
    return _wrapper

それはよりコンパクトで、より Pythonic であり、すべてのケースで問題なく動作するはずです。

于 2012-05-28T17:06:48.270 に答える