【问题标题】:Python - is there a way to implement __getitem__ for multidimension array?Python - 有没有办法为多维数组实现 __getitem__ ?
【发布时间】:2013-07-02 22:20:56
【问题描述】:

我想使用类似的东西:

class Board():
    ...
    def __getitem__(self, y, x):
        return self.board[y][x]

但不幸的是,当我打电话时:

board[x][y]

我得到: TypeError: __getitem__() takes exactly 3 arguments (2 given)

【问题讨论】:

    标签: python arrays python-2.7 numpy multidimensional-array


    【解决方案1】:

    当您执行board[x][y] 时,您将两次 调用__getitem__,因为您正在执行两个单独的访问:[x] 是一个,[y] 是另一个。没有办法直接在__getitem__ 中处理这个问题;你必须让board[x] 返回某种子对象,你可以使用[y] 来获取单个项目。你可能想要的是让__getitem__ 接受一个元组:

    def __getitem__(self, tup):
        y, x = tup
        return self.board[y][x]
    

    然后做:

    board[x, y]
    

    (请注意,您在 __getitem__board[x][y] 之间切换了 x 和 y 的顺序 --- 这是故意的吗?)

    【讨论】:

    • 完美!正是我正在寻找的用于处理工作表的帮助类。我想通过列号或名称来寻址,这允许我以最小的语法开销一起传递行和列。
    【解决方案2】:

    您可能需要考虑使用以下语法:

    board[(x, y)]
    

    它不那么漂亮,但它允许您简单地拥有多维数组。实际上是任意数量的维度:

    board[(1,6,34,2,6)]
    

    通过将 board 设为默认字典,您甚至可以拥有稀疏字典:

    board[(1,6,34,2,6)]
    
    >>> from collections import defaultdict
    >>> board = defaultdict(lambda: 0)
    >>> board[(1,6,8)] = 7
    >>> board[(1,6,8)]
    7
    >>> board[(5,6,3)]
    0
    

    如果您想要比NumPy 更高级的东西。

    【讨论】:

    • 这里的游戏已经很晚了,但是括号是不必要的,因为逗号是元组运算符而不是括号。虽然 defaultdict 的东西很酷。
    【解决方案3】:

    board[x][y] 表示board.__getitem__(x).__getitem__(y),因此Board.__getitem__ 必须返回某种同样支持__getitem__ 并记住x 的视图。这有点工作,但对于某些用例(涉及传递该视图的任何事情)来说,它非常方便。

    另一个选项是board[x, y],表示board.__getitem__((x, y))。请注意,这会将一个元组传递给__getitem__,您必须手动解压缩(在 2.x 中有用于执行此操作的语法糖,但它有点晦涩,并且在 3.x 中也消失了,所以您可能想要为了将来的移植工作,请避免使用它)。

    【讨论】:

      【解决方案4】:

      只要做:

      class Board():
          def __getitem__(self, x):
              return self.board[x]
      

      因为当你调用b[x][y]时它实际上调用了两次__getitem__(),如下所示:

      import numpy as np
      b = Board()
      b.board = np.random.random((3,3,3))
      print (b[2][0]==(b[2])[0]).all()
      #True
      

      但最好将np.ndarray 子类化,这样您就不必重新实现此方法:

      class Board(np.ndarray):
          pass
      

      【讨论】:

        【解决方案5】:

        说 b 是类对象 b = Board()。当您正在寻找B[0][0] __getitem__ 时将无法正常工作。相反,我们可以做的是设置 b 的数据等于一个新变量。

        boardData = b.data
        
        print(boardData[0][0]) 
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-10-18
          • 1970-01-01
          • 2021-04-21
          • 1970-01-01
          相关资源
          最近更新 更多