为什么多个列表索引可以与_getitem而不是_setitem一起使用__

2024-06-02 14:03:27 发布

您现在位置:Python中文网/ 问答频道 /正文

考虑下面的代码:

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__内部运行的任何其他代码都不会被调用


Tags: selfdataindexreturnvaluedefcolrow
3条回答

您的__getitem__只是返回第一级子列表,因此您可以继续使用下标访问第二级子列表,依此类推,因为返回列表有自己的__getitem__实现

另一方面,您的__setitem__需要一个3项元组,因此这应该是您想要的__setitem__

myMDL2[0, 0, 0] = 12 # instead of myMDL2[0][0][0] = 12

另一方面,如果您希望能够做到:

myMDL2[0][0][0] = 12

您甚至不需要实现__setitem__,因为myMDL2[0]返回第一个子列表,myMDL2[0][0]返回myMDL2[0]的第一个子列表,然后myMDL2[0][0][0] = 12将调用myMDL2[0][0]返回的列表的__setitem__方法

因为

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的调用

相关问题 更多 >