如何在 python 中实现引用列表?

How to implement a list of references in python?

我正在尝试为 python (2) 中的一组对象建模。集合应该使对象的特定属性(整数、浮点数或任何不可变对象)可通过列表接口使用。

(1)

>>> print (collection.attrs)
[1, 5, 3]
>>> collection.attrs = [4, 2, 3]
>>> print (object0.attr == 4)
True

我特别希望集合中的这个列表接口允许重新分配单个对象的属性,例如

(2)

>>> collection.attrs[2] = 8
>>> print (object2.attr == 8)
True

我确信这是一种经常发生的情况,不幸的是我无法在 Whosebug / google 等上找到关于如何实现它的令人满意的答案

在幕后,我希望 object.attr 实现为可变对象。不知何故,我还希望该集合将 "list of references" 保存到 object.attr 而不是各自引用的(不可变)值本身。

请教您如何以优雅灵活的方式解决此问题。

允许 (1) 但不允许 (2) 的可能实现是

class Component(object):
    """One of many components."""
    def __init__(self, attr):
        self.attr = attr

class System(object):
    """One System object contains and manages many Component instances.
    System is the main interface to adjusting the components.
    """
    def __init__(self, attr_list):
        self._components = []
        for attr in attr_list:
            new = Component(attr)
            self._components.append(new)

    @property
    def attrs(self):
        # !!! this breaks (2):
        return [component.attr for component in self._components] 
    @attrs.setter
    def attrs(self, new_attrs):
        for component, new_attr in zip(self._components, new_attrs):
            component.attr = new_attr

这个!!!换行符 (2),因为我们创建了一个新列表,其条目是对所有 Component.attr 值的引用,而不是对属性本身的引用。

感谢您的意见。

TheXMA

只需在中间添加另一个代理:

class _ListProxy:
    def __init__(self, system):
        self._system = system

    def __getitem__(self, index):
        return self._system._components[index].attr

    def __setitem__(self, index, value):
        self._system._components[index].attr = value


class System:
    ...
    @property
    def attrs(self):
        return _ListProxy(self)

您可以通过实施所有其他 list 方法使代理更漂亮,但这对于您的用例来说已经足够了。

@filmor 非常感谢您的回答,完美解决了问题!我让它更通用一点:

class _ListProxy(object):
    """Is a list of object attributes. Accessing _ListProxy entries
    evaluates the object attributes each time it is accessed,
    i.e. this list "proxies" the object attributes.
    """
    def __init__(self, list_of_objects, attr_name):
        """Provide a list of object instances and a name of a commonly
        shared attribute that should be proxied by this _ListProxy
        instance.
        """
        self._list_of_objects = list_of_objects
        self._attr_name = attr_name

    def __getitem__(self, index):
        return getattr(self._list_of_objects[index], self._attr_name)

    def __setitem__(self, index, value):
        setattr(self._list_of_objects[index], self._attr_name, value)

    def __repr__(self):
        return repr(list(self))

    def __len__(self):
        return len(self._list_of_objects)

是否缺少任何重要的列表方法?

如果我希望某些组件(对象)被垃圾回收怎么办? 我是否需要使用像 WeakList 这样的东西来防止内存泄漏?