__getitem__在列表列表中包含切片

时间:2013-11-17 15:30:29

标签: python python-2.7 nested-lists slice

我正在创建一个表示列表列表的类。 __getitem__令我头疼。一切都顺其自然,直到我引入切片作为参数。

演示代码

# Python version 2.7.5

class NestedLists:
   _Cells = [['.', '.', '.', '.', '.'],
             ['.', '.', 'N', '.', '.'],
             ['.', 'C', 'A', 'T', '.'],
             ['.', '.', 'P', '.', '.'],
             ['.', '.', '.', '.', '.']]

   def __getitem__(self, index):
      if isinstance(index, int):
         return self._Cells[index]
      elif isinstance(index, slice):
         return self._Cells[index]
      else:
         raise TypeError, "Invalid argument type"

nested = NestedLists()

print "Expecting A"
print nested[2][2]

print "Expecting CAT"
print nested[2][1:4]

print "Expecting ..N.."
print "          .CAT."
print "          ..P.."
print nested[1:4]

print "Expecting .N."
print "          CAT"
print "          .P."
print nested[1:4][1:4]

输出

Expecting A
A
Expecting CAT
['C', 'A', 'T']
Expecting ..N..
          .CAT.
          ..P..
[['.', '.', 'N', '.', '.'], ['.', 'C', 'A', 'T', '.'], ['.', '.', 'P', '.', '.']]
Expecting .N.
          CAT
          .P.
[['.', 'C', 'A', 'T', '.'], ['.', '.', 'P', '.', '.']]

显然,正在发生的事情是第二个[]操作符调用正在应用于第一个...的输出...但保留在最外层列表的上下文中。然而,解决方案使我望而却步。

2 个答案:

答案 0 :(得分:4)

您可能希望将多维访问的语法从obj[row][col]更改为使用单个元组索引:obj[row, col]。这是numpy ndarray类型使用的格式,它非常有用,因为它可以让您一次查看索引的所有维度。您可以编写一个允许在任何维度切片的__getitem__

def __getitem__(self, index):
   row, col = index
   if isinstance(row, int) and isinstance(col, (int, slice)):
      return self._Cells[row][col]
   elif isinstance(row, slice) and isinstance(col, (int, slice)):
      return [r[col] for r in self._Cells[row]]
   else:
      raise TypeError, "Invalid argument type"

答案 1 :(得分:1)

__getitem__是切片时index的回复是列表清单:

[['.', '.', 'N', '.', '.'], ['.', 'C', 'A', 'T', '.'], ['.', '.', 'P', '.', '.']]

第二个切片将索引到此列表中,而不是将切片应用于列表中的每个项目。

要获得您正在寻找的行为,当NestedLists.__getitem__是切片时,您可以NestedListsSlice返回一个新类index。然后,这可以定义自己的__getitem__以将第二个索引应用于:

class NestedLists:
    ...
    def __getitem__(self, index):
        ...
        elif isinstance(index, slice):
            return NestedListsSlice(self._Cells[index])
        ...

class NestedListsSlice():
    def __init__(self, _Cells):
        self._Cells = _Cells
    def __getitem__(self, index):
        if isinstance(index, int) or isinstance(index, slice):
            return list(x[index] for x in self._Cells)
        else:
            raise TypeError