我想创建一个对象列表,它代表具有相同属性的对象的整个类别(假设是可见的对象)。但是,一旦我将对象追加到其中一个子组,它就不会更新所有可见对象的列表(visible_objects)。这对我来说是已知的Python行为,但我想知道实现这一点的最佳实践是什么,所以它以干净无缝的方式将元素也附加到组合列表(visible_objects)。(例如,每当我将新元素添加到其中一个子组时)
class A:
def __init__(self,i):
self.i=i
images=[A(1),A(2),A(3)]
images2=[A(4),A(5)]
visible_objects=images+images2
images.append(A(6))
print([x.i for x in images])
print([x.i for x in images2])
print([x.i for x in visible_objects])
[1, 2, 3, 6]
[4, 5]
[1, 2, 3, 4, 5]
我希望最后一个列表也包含6没有重新分配visible_objects后每次追加。非常感谢。
好的,我想我算是解决了这个问题,但我不确定这是不是最好的方法。
class A:
def __init__(self,i):
self.i=i
class MagicList:
def __init__(self,elements=[],referenced_lists=None):
self.elements=elements
self.referenced_lists=referenced_lists
self.embedded_in_lists=[]
if self.referenced_lists is not None:
self.elements=[]
for i,magic_list in enumerate(self.referenced_lists):
for item in magic_list.elements:
self.elements.append(item)
self.referenced_lists[i].embedded_in_lists.append(self)
def append(self,obj):
self.elements.append(obj)
for i,list1 in enumerate(self.embedded_in_lists):
self.embedded_in_lists[i].elements=[]
for j in range(len(list1.referenced_lists)):
self.embedded_in_lists[i].elements+=list1.referenced_lists[j].elements
def pop(self,index):
self.elements.pop(index)
for i,item in enumerate(self.embedded_in_lists):
item.elements.pop(index)
def __str__(self):
return(str(self.elements))
m=MagicList([1,3,4])
m2=MagicList([2,5,8])
m3=MagicList(referenced_lists=[m,m2])
print(m)
print(m2)
print(m3)
images=MagicList([A(1),A(2),A(3)])
images2=MagicList([A(4),A(5)])
visible_objects=MagicList(referenced_lists=[images,images2])
print([x.i for x in images.elements])
print([x.i for x in visible_objects.elements])
images.append(A(6))
print([x.i for x in images.elements])
print([x.i for x in visible_objects.elements])
images.pop(3)
print([x.i for x in images.elements])
print([x.i for x in visible_objects.elements])
结果:
[1, 3, 4]
[2, 5, 8]
[1, 3, 4, 2, 5, 8]
[1, 2, 3]
[1, 2, 3, 4, 5]
[1, 2, 3, 6]
[1, 2, 3, 6, 4, 5]
[1, 2, 3]
[1, 2, 3, 4, 5]
您的答案是一个很好的方法,但是您也可以通过在MagicList
中定义返回正确元素的__getitem__()
来实现这一点。这样,您就不需要花时间将每个列表中的元素克隆或复制到一个大的"超级列表"中,也不需要花时间修改"子列表"。当您尝试获取MagicList
对象的索引时,将无缝地反映
class MagicList():
def __init__(self, *referenced_lists):
self.lists = referenced_lists
def __getitem__(self, index):
cum_len = 0
for sublist in self.lists:
sublist_start_index = cum_len
sublist_end_index = cum_len + len(sublist)
if sublist_end_index > index:
return sublist[index - sublist_start_index]
cum_len = sublist_end_index
raise IndexError("list index out of range")
def __str__(self):
return str([x for x in self])
def add_list(self, new_list):
if isinstance(new_list, list): # If new_list is a list, append it to self.lists
self.lists.append(new_list)
else: # Try to convert new_list to a list and append that
try:
self.lists.append(list(new_list))
except TypeError: # new_list is not an iterable, so list(new_list) throws a TypeError
self.lists.append([new_list])
然后,你可以这样做:
l1 = [1, 2, 3, 4, 5]
l2 = [100, 200, 300, 400, 500]
m = MagicList(l1, l2) # You can give this any number of lists
print("Original list: ")
print(m)
l1.append(-1)
print("Appending to l1: ")
print(m)
l2.append(1000)
print("Appending to l2: ")
print(m)
l1[0] = 'abc'
print("Modifying l1: ")
print(m)
l2[-2] = 'def'
print("Modifying l2: ")
print(m)
del l1[0]
print("Removing from l1: ")
print(m)
del l2[-1]
print("Removing from l2: ")
print(m)
输出如下:
Original list:
[1, 2, 3, 4, 5, 100, 200, 300, 400, 500]
Appending to l1:
[1, 2, 3, 4, 5, -1, 100, 200, 300, 400, 500]
Appending to l2:
[1, 2, 3, 4, 5, -1, 100, 200, 300, 400, 500, 1000]
Modifying l1:
['abc', 2, 3, 4, 5, -1, 100, 200, 300, 400, 500, 1000]
Modifying l2:
['abc', 2, 3, 4, 5, -1, 100, 200, 300, 400, 'def', 1000]
Removing from l1:
[2, 3, 4, 5, -1, 100, 200, 300, 400, 'def', 1000]
Removing from l2:
[2, 3, 4, 5, -1, 100, 200, 300, 400, 'def']
一些要记住的东西:如果你想添加/插入任何不在引用列表中的MagicList
,你需要将其包装在列表中。