我正在尝试在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
我确信这是一个经常发生的情况,遗憾的是我无法找到关于如何在stackoverflow / google等上实现它的令人满意的答案。
在幕后,我希望将object.attr
实现为可变对象。不知怎的,我还希望集合能够保存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
答案 0 :(得分:2)
只需在中间添加另一个代理:
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
方法来让代理爱好者成为现实,但这足以满足您的使用需求。
答案 1 :(得分:0)
@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之类的东西来防止内存泄漏?