【问题标题】:Property decorator with optional argument带有可选参数的属性装饰器
【发布时间】:2020-02-14 10:40:24
【问题描述】:

我想用一个接受可选参数的装饰器创建一个类属性。通常我会写

def MyProperty(func, optional=None):
    def getter():
        """magic goes here"""
        return func() if not optional else optional(func())
    return property(getter)

class MyClass(object):
    @MyProperty
    def myFunction(foo):
        return foo

MyClass().myFunction(5.)
>>> 5.0

这一切都很好,但是当我现在也像这样沿着装饰器传递一个函数时:

class MyClass(object):
    @MyProperty(int)
    def myFunction(foo):
        return foo

我现在打电话

MyClass().myFunction(5)
>>> TypeError: 'property' object is not callable 

虽然我希望得到int(5) 作为结果。

【问题讨论】:

  • 你如何定义@MyProperty?

标签: python properties attributes decorator python-2.x


【解决方案1】:

当你写作时

@MyProperty(int)
def myFunction(foo)
    ...

这意味着调用MyProperty(int),然后以myFunction 作为参数调用返回的任何内容。所以MyProperty应该是一个返回函数的函数,接受一个函数,返回一个函数。

所以你可以这样写你的装饰器:

def MyProperty(optional=None):
    def decorator(func):
        def getter(*args, **kwargs):
            """unspecified magic goes here"""
            return func(*args, **kwargs) if not optional else optional(func(*args, **kwargs))
        return getter
    return decorator

所以MyProperty(int) 返回一个函数 (decorator),decorator 返回你正在装饰的任何东西。

但是,当您在没有参数的情况下调用它时,您仍然需要将其称为 @MyProperty() 而不是 @MyProperty,否则您会错过展开的阶段。

>>> class MyClass:
...    @MyProperty()
...    def f1(foo):
...      return foo
...    @MyProperty(int)
...    def f2(foo):
...      return foo
...
>>> MyClass.f1(1.5)
1.5
>>> MyClass.f2(1.5)
1

我不确定您是否使用property。示例中的两个函数都只是类中的函数。它们没有self 参数或cls 参数,并且您是从类本身而不是从实例调用它们。有点不清楚你的目标是什么。

当我在 Python 2 中尝试此操作时,我必须将函数声明为静态方法才能使其工作。

>>> class MyClass(object):
...    @staticmethod
...    @MyProperty()
...    def f1(foo):
...      return foo
...    @staticmethod
...    @MyProperty(int)
...    def f2(foo):
...      return foo
...
>>> MyClass.f1(0.5)
0.5
>>> MyClass.f2(1.5)
1

【讨论】:

  • 感谢您的解释。我花了一段时间才真正弄清楚它背后的协议是什么,但现在我明白了。谢谢
猜你喜欢
  • 1970-01-01
  • 2015-01-25
  • 2020-06-20
  • 1970-01-01
  • 2014-07-21
  • 1970-01-01
  • 1970-01-01
  • 2018-01-07
相关资源
最近更新 更多