首页 > 解决方案 > 不可变列表属性

问题描述

如何创建一个始终包含相同列表的类属性?尽管可以更改列表的内容,但它应该始终引用相同的列表。

显而易见的解决方案是使用属性。

class Table(list):
    def filter(kwargs):
    """Filter code goes here."""


class db:
    _table = Table([1, 2])
    table = property(lambda self: self._table)


db.table.append(3)

我会假设 db.table 应该返回一个列表,并且您应该能够附加到这个列表。但是不,这段代码抛出了一个异常:

AttributeError: 'property' object has no attribute 'append'

如何创建始终引用同一个列表的属性?

插图:

db.table = [x for x in db.table if x > 2]
db.filter(3)    # This filter method got lost when reassigning the table in the previous line.

标签: python

解决方案


这是使用类属性的解决方案,使用以下答案:如何制作类属性?

class ClassPropertyDescriptor(object):

    def __init__(self, fget, fset=None):
        self.fget = fget
        self.fset = fset

    def __get__(self, obj, klass=None):
        if klass is None:
            klass = type(obj)
        return self.fget.__get__(obj, klass)()

    def __set__(self, obj, value):
        if not self.fset:
            raise AttributeError("can't set attribute")
        type_ = type(obj)
        return self.fset.__get__(obj, type_)(value)

    def setter(self, func):
        if not isinstance(func, (classmethod, staticmethod)):
            func = classmethod(func)
        self.fset = func
        return self

def classproperty(func):
    if not isinstance(func, (classmethod, staticmethod)):
        func = classmethod(func)

    return ClassPropertyDescriptor(func)


class db(object):
        _table = [1,2]

        @classproperty
        def table(cls):
                return list(cls._table)



t = db.table
t.append(3)
print t  # [1, 2, 3]
print db.table  # [1, 2]

推荐阅读