为什么多个列表索引可以用于__getitem__但不能用于__setitem__
考虑以下代码:
class multiDimList1(object):
def __init__(self):
self.data = [[[0, 1, 2], [3, 4, 5], [6, 7, 8]],
[[0, 1, 2], [3, 4, 5], [6, 7, 8]]]
def __getitem__(self, index):
print("MDL1 getitem")
return self.data[index]
def __setitem__(self, index, value):
print("MDL1 setitem")
index, row, col = index
self.data[index][row][col] = value
def __str__(self):
return ','.join(str(e) for e in self.data)
class multiDimList2(object):
def __init__(self):
self.data = [[[0, 1, 2], [3, 4, 5], [6, 7, 8]],
[[0, 1, 2], [3, 4, 5], [6, 7, 8]]]
def __getitem__(self, index):
print("MDL2 getitem")
return self.data[index]
def __setitem__(self, index, value):
print("MDL2 getitem")
index, row, col = index
self.data[index][row][col] = value
def __str__(self):
return ','.join(str(e) for e in self.data)
myMDL1 = multiDimList1()
myMDL2 = multiDimList2()
myMDL1[0, 0, 0] = 12
print(myMDL1)
myMDL2[0][0][0] = 12
print(myMDL2)
输出:
MDL1 setitem
[[12, 1, 2], [3, 4, 5], [6, 7, 8]],[[0, 1, 2], [3, 4, 5], [6, 7, 8]]
MDL2 getitem
[[12, 1, 2], [3, 4, 5], [6, 7, 8]],[[0, 1, 2], [3, 4, 5], [6, 7, 8]]
为什么我可以使用 myMDL2[0][0][0]
来获取值,而 __getitem__
能正确处理这个操作,但当我尝试给这个索引赋值时却没有调用 __setitem__
呢?
myMDL2[0][0][0] = 12
其实是通过 __getitem__
创建了一个对正确索引的引用,然后以这种方式设置值。这就意味着我在 __setitem__
中想要执行的任何其他代码都不会被调用。
相关问题:
- 暂无相关问题
3 个回答
0
另一方面,如果你想要能够这样做:
myMDL2[0][0][0] = 12
你甚至不需要实现 __setitem__
这个方法,因为 myMDL2[0]
会返回第一个子列表,而 myMDL2[0][0]
会返回 myMDL2[0]
的第一个子列表,然后 myMDL2[0][0][0] = 12
这行代码会调用 myMDL2[0][0]
返回的列表的 __setitem__
方法。
2
你的 __getitem__
方法只是返回了第一层的子列表,所以你可以继续使用下标来访问第二层的子列表,依此类推,因为返回的列表有自己的 __getitem__
实现。
而你的 __setitem__
方法则期望接收一个包含三个元素的元组,所以你应该把这个三元组传给 __setitem__
:
myMDL2[0, 0, 0] = 12 # instead of myMDL2[0][0][0] = 12
3
这是因为
myMDL1[0, 0, 0] = 12
等同于
myMDL1.__setitem__(index=(0,0,0), value=12)
不过,
myMDL2[0][0][0] = 12
等同于
myMDL2.__getitem__(index=0)[0][0] = 12
这意味着首先要完成 myMDL2[0]
,我们获取它的第一个项目,最后我们把这个项目的值设置为12。
myMDL2[0][0][0] = 12
=> myMDL2.__getitem__(index=0)[0][0] = 12
=> [[0, 1, 2], [3, 4, 5], [6, 7, 8]][0][0] = 12
=> [[0, 1, 2], [3, 4, 5], [6, 7, 8]].__getitem__(index=0)[0] = 12
=> [0, 1, 2][0] = 12
=> [0, 1, 2].__setitem__(index=0, value=12)
=> [12, 1, 2]
不太确定我是否解释清楚了,__setitem__
并没有在你的 multiDimList2 上被调用。