可迭代属性

11 投票
3 回答
7599 浏览
提问于 2025-04-17 06:40

我有一个库(django-piston),它希望类的一些参数作为类的属性。我想在一个方法中动态地定义这个值。所以我想做类似这样的事情:

class MyHandler(BaseHandler):
    @property
    def fields(self):
        fields = self.model._meta.fields + self.model._meta.virtual_fields
        # Do something more with fields
        return fields

但是这样做失败了,错误信息是:

'property' object is not iterable

所以我想做类似这样的事情:

class iterable_property(property):
    def __iter__(self):
        # What here?

但我在这里遇到了困难。我该如何获取一个可以被遍历的属性呢?

3 个回答

1

如果我理解得没错,在django-piston中,一个处理器可以有一些类属性,比如modelfields

如果是这样的话,你的问题可以通过以下方式解决:

class MyHandler(BaseHandler):
    model = Post
    class __metaclass__(type):
        @property
        def fields(cls):
            fields = cls.model._meta.fields + cls.model._meta.virtual_fields
            # Do something more with fields
            return fields
2

Sven Marnach给了我一个很好的建议。他告诉我,问题并不是因为属性类不支持迭代,而是因为我在一个类上调用了它。所以我做了以下修改:

class class_property(property):
    def __get__(self, instance, type):
        if instance is None:
            return super(class_property, self).__get__(type, type)
        return super(class_property, self).__get__(instance, type)

现在它可以正常工作了。;-)

14

你原来的代码看起来没问题(不过我不会把局部变量命名成和外部函数一样的名字)。

要注意,属性只在新式类中有效,所以你需要从 object 继承。此外,你需要通过一个实例来调用属性。

如果你需要一个类属性,那么 property 就不适用了,你需要自己写一个描述符来处理类级别的属性:

class ClassProperty(object):
    def __init__(self, func):
        self.func = func
    def __get__(self, inst, cls):
        return self.func(cls)

class A(object):
    model_fields = ['field1', 'field2', 'field3']

    @ClassProperty
    def fields(cls):
        return cls.model_fields + ['extra_field']

print A.fields

撰写回答