python - 在 Python 2.7 中定义类似 "property"的装饰器

标签 python decorator

我正在尝试编写一个类似于@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}?

最佳答案

实际上,它会引发 TypeError。

无论如何,在使用函数运行装饰器时我也遇到了同样的错误。发生这种情况是因为,当您使用 @foo.before 修饰函数时,它将调用 self._before 函数,并将修饰后的函数作为参数。由于 self._beforeNone,因此会引发错误。

有多种解决方案。我最喜欢的是为 ​​self._before 设置一个不同的默认值 - 一个将设置 self._before 值的函数:

class Dec(object):
  def __init__(self, fn):
    self._fn = fn
    def setbefore(b):
        self._before = b
    self._before = self.default_before = setbefore

当然,这个函数不应该在调用Dec对象时被调用,所以我们改变__call__方法:

  def __call__(self, *args, **kwargs):
      if self._before != self.default_before:
         self._before(*args, **kwargs)
      self._fn(*args, **kwargs)

关于python - 在 Python 2.7 中定义类似 "property"的装饰器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10787667/

相关文章:

python - 如何向 Firestore 中的现有数组添加非唯一元素?

python - python如何比较字符串和整数

c# - 如何注册手动创建的装饰器实例

php - 从方法不修改功能的装饰器调用方法的正确方法是什么?

angular - 为什么 Angular 2 使用装饰器?

python - 怎么 "mark"一组Python方法供以后使用? (这些装饰器可以改进吗?)

Python url标题问题

python - 一次读取多个 Python pickle 数据,缓冲和换行?

python - XPath 匹配每个包含文本的节点

c# - 如何使用 structuremap asp.net mvc 注册可选装饰器或带有可选参数的装饰器?