用于字段的Python修饰器

2022-04-07 00:00:00 python decorator design-patterns

问题描述

我知道根本没有这回事。这就是为什么我在找一些很好的同类产品。上这节课:

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’这样的基类,然后检查类型-这样每次我有新类型时都必须生成这个类,所以我也不喜欢这个解决方案。

还有其他想法吗?


解决方案

修饰符只是函数调用的语法糖,所以要对属性应用修饰符,只需在初始化器上调用它:

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']

相关文章