【问题标题】:Python Decorators on Class Level Variables as Metadata for Reflection?类级别变量上的 Python 装饰器作为反射的元数据?
【发布时间】:2013-01-14 05:42:41
【问题描述】:

我有一个 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(...)

但是,装饰器实际上是在进行函数柯里化,并且由于类变量定义只是将 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"
    }

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

【问题讨论】:

  • 您说扩展PropertyClass 是一个问题,因为它向所有类添加了行为——但这很容易做到,只需添加一个基类。见鬼,即使那不可能,你甚至可以用猴子修补它。
  • 我喜欢很好的猴子补丁!
  • 有什么理由让您更喜欢“Variable_one changed from ...”而不是“variable_one ...”=为什么要显示另一个名称而不是原始名称?你看过 dir() 函数吗?或 MyClass.__dict__ ?
  • @Lattyware 我无权访问各种属性类,因为它们是谷歌应用程序引擎属性类,所以我能想到的唯一方法是从每个属性类中派生。
  • @User 因为这个字符串将显示给用户,但变量的内部名称可能有点过于技术性

标签: python reflection decorator python-decorators


【解决方案1】:

数据存储区属性类是描述符(如 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

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

【讨论】:

    猜你喜欢
    • 2012-08-14
    • 1970-01-01
    • 1970-01-01
    • 2011-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-16
    • 2012-11-24
    相关资源
    最近更新 更多