字段的python装饰器

时间:2012-11-23 16:29:01

标签: python design-patterns decorator

我知道没有这样的事情。这就是为什么我正在寻找一些不错的等价物。有这个课程:

class MyClass:
   a = 5
   b  = "foo"
   c = False

我想将字段a和b“分组”在一起,以便能够以某种方式迭代来自该组的成员。所以有一些场装饰器会很好,比如:

class MyClass:
   @bar
   a = 5
   @bar
   b  = "foo"
   c = False

有一些像myDir(MyClass,'bar')这样的函数会返回('a','b')。

到目前为止,我们有哪些选择?  1.按照'a_bar','b_bar'之类的特殊约定命名这些字段 - 但遗憾的是我不能这样做。  2.将名称列表作为另一个类成员 - 我想保持这个分组属性接近属性,所以我不喜欢这种方法。  3.而不是将5分配给'a'和'foo',我可以创建继承自整数和字符串的类,并添加另一个基类,如'Group',然后检查类型 - 这样我将不得不生成这个类每次我有新类型,所以我也不喜欢这个解决方案。

还有其他想法吗?

2 个答案:

答案 0 :(得分:2)

装饰器只是函数调用的语法糖,因此要将装饰器应用于属性,只需在初始化器上调用它:

a = bar(5)

在您的情况下,您可以创建实现描述符协议的对象:

class GroupedAttribute(object):
    def __init__(self, group, obj):
        self.group = group
        self.obj = obj
    def __get__(self, obj, owner):
        return self.obj
    def __set__(self, obj, value):
        self.obj = value

为了优雅,您可以为属性组编写一个类:

class GroupedAttribute(object):
    def __init__(self, group, obj):
        self.group = group
        self.obj = obj
    def __get__(self, obj, owner):
        return self.obj
    def __set__(self, obj, value):
        self.obj = value

class AttributeGroup(object):
    def __call__(self, obj):
        return GroupedAttribute(self, obj)
    def __get__(self, obj, owner):
        return BoundAttributeGroup(self, obj, owner)

class BoundAttributeGroup(object):
    def __init__(self, group, obj, owner):
        self.group = group
        self.obj = obj
        self.owner = owner
    def __dir__(self):
        items = dir(self.owner if self.obj is None else self.obj)
        return [item for item in items if
                getattr(self.owner.__dict__.get(item, None),
                        'group', None) is self.group]

用法:

class MyClass(object):
    bar = AttributeGroup()
    a = bar(5)
    b = bar("foo")
    c = False
dir(MyClass.bar)    # ['a', 'b']

答案 1 :(得分:0)

如果要保留变量名以便稍后引用,可以使用字典。因此,您的对象中的此代码...

self.dict_bar_props = {}

self.dict_bar_props["a"] = 5
self.dict_bar_props["b"] = "foo"
self.dict_bar_props["c"] = False

...稍后访问该对象的属性时会给你这个结果:

objectName = myObject()
objectName.dict_bar_props["a"]
>> 5

如果你想保持变量名完全分开但稍后根据定义的命名约定找到它们,那么你可以使用hacky,它只返回前缀为“bar_”的变量名,例如:

import re
varnames = dir(objectName)
list_of_property_names    = [ a for a in varnames if re.match("bar_", a) ]