__getitem__ with slices on a list of lists

风格不统一 提交于 2020-01-04 15:31:58

问题


I'm creating a class representing a list of lists. __getitem__ is giving me headaches. Everything goes swimmingly until I introduce slices as parameters.

Demonstration code

# 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]

Output below

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', '.', '.']]

Apparently, what is happening is that the second [] operator call is being applied to the output of the first... but staying in the context of the outermost list. The solution eludes me however.


回答1:


You probably want to change your syntax for mutidimensional access from obj[row][col] to using a single tuple index: obj[row, col]. This is the format numpy's ndarray type uses, and its very helpful, as it lets you see all the dimentions of the index at once. You can write a __getitem__ that will allow slicing in any dimension:

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"



回答2:


The return from __getitem__ when index is a slice is a list of lists:

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

The second slice indexes into this list, rather than applying the slice to each item in the list.

To get the behaviour you're looking for, you could make NestedLists.__getitem__ return a new class, NestedListsSlice when index is a slice. This could then define its own __getitem__ to apply the second index to:

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


来源:https://stackoverflow.com/questions/20032493/getitem-with-slices-on-a-list-of-lists

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!