6

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

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.我可以创建从整数和字符串继承的类,并添加另一个基类,如“Group”,然后检查类型,而不是将 5 分配给“a”和“foo”,这样我就必须生成这个类每次我有新的类型,所以我也不喜欢这个解决方案。

还有其他想法吗?

4

2 回答 2

8

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

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']
于 2012-11-23T16:52:39.347 回答
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) ]
于 2012-11-23T16:40:02.677 回答