类级变量上的Python装饰器作为反射的元数据?

时间:2013-01-30 12:00:10

标签: python reflection decorator python-decorators

我有一个python类(实际上是它的Google App Engine模型),如下所示:

class MyClass(ParentClass):
    variable_one = PropertyClass(...)
    variable_two = PropertyClass(...)

我打算构建一个系统,该系统可以描述此类的两个实例之间的差异,这两个实例代表不同时间点的实体的两个版本。最终会产生类似

的字符串
"Variable One changed from 'foo' to 'bar', Variable Two changed from empty to 'baz'"

所以,我需要在某个地方存储“variable_one”应该显示为“Variable One”的事实,依此类推。来自C#背景,我的直觉是使用属性,例如:

class MyClass : ParentClass
{
    [DisplayName("Variable One")]
    public PropertyClass variable_one;

    [DisplayName("Variable Two")]
    public PropertyClass variable_two;
}

首先,python等效似乎是装饰器:

class MyClass(ParentClass):
    @display_name("Variable One")
    variable_one = PropertyClass(...)

    @display_name("Variable Two")
    variable_two = PropertyClass(...)

然而,装饰器实际上正在进行函数currying,并且因为类变量定义只是将PropertyClass的实例分配给variable_one和variable_two,所以它看起来不像是有效的python。无论如何,我不确定我是怎么写的。

一个选项似乎是扩展PropertyClass ...

class MyClass(ParentClass):
    variable_one = MyPropertyClass("Variable One", ...)
    variable_two = MyPropertyClass("Variable Two", ...)

但是有一些不同的属性类被使用,我想为所有这些属性添加一个共同的行为,所以这似乎太费力了。

我想我可以定义字典:

class MyClass(ParentClass):
    variable_one = PropertyClass(...)
    variable_two = PropertyClass(...)
    variable_display_names = {
        "variable_one": "Variable One",
        "variable_two": "Variable Two"
    }

但我希望听到一些更有经验的pythoners关于实现这一目标的最佳pythonic方式。

1 个答案:

答案 0 :(得分:4)

数据存储属性类是描述符(如python @property装饰器),但作为不实现__setattr__的自定义类,您可以在这些对象上设置任意属性:

 class MyClass(ParentClass):
     variable_one = PropertyClass(...)
     variable_one.display_name = "Variable One"

     variable_two = PropertyClass(...)
     variable_two.display_name = "Variable Two"

可以通过以下方式推广到装饰器:

def display_name(dispname):
    def decorate_with_display_name(prop):
        prop.display_name = dispname
        return prop
    return decorate_with_display_name

只要您通过类(而不是实例)访问Property,就可以再次检索这些值;例如,给定一个实例,您可以print type(instance).variable_two.display_name