切片是Python重要的特性之一.与切片密切相关的是索引.一般情况下索引的返回值是序列的元素,切片的返回值是序列:
如下:
1 2 3 4 5 t = tuple (i for i in range (10 )) print(t[1 ]) print(t[1 :3 ])
而在序列调用[ ] 时,默认调用的是__getitem__方法.
为了能够构建符合Python风格的索引与切片操作,或者为了学习Python的切片原理,我们对其切片进行分析.
定义一个索引返回类进行查看
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class mySeq : def __getitem__ (self, index ): return index s = mySeq() print(s[1 ]) print(s[1 :4 ]) print(s[1 :4 :2 ]) print(s[1 :4 :2 ,9 ]) print(s[1 :4 :2 , -5 :])
当仅仅进行索引操作时返回的是数字
当仅一个切片操作时返回的是slice对象
当不仅一个切片操作时返回的时slice元组
slice类情况分析
1 2 3 4 5 print(slice ) print(dir (slice ))
上面的slice对象包含有诸多属性,其中start,stop,step我们都很清楚了.indices属性很关键.我们可以看下其解释:
1 2 3 4 5 6 7 8 9 10 print(help (slice .indices)) indices(...) S.indices(len) -> (start, stop, stride) Assuming a sequence of length len , calculate the start and stop indices, and the stride length of the extended slice described by S. Out of bounds indices are clipped in a manner consistent with the handling of normal slices. None
那么slice的作用就是把你输入的start,stop,step进行计算,获得正确的索引:例如:
1 2 3 4 print(slice (None , 10 ,2 ).indices(10 )) print(slice (-3 ,None , None ).indices(5 )) (0 , 10 , 2 ) (2 , 5 , 1 )
这里我们已经知道getitem中该如何操作啦:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 from array import arrayimport reprlibimport mathimport numbersimport functoolsimport operatorimport itertools class Vector : typecode = 'd' def __init__ (self, components ): self._components = array(self.typecode, components) def __iter__ (self ): return iter (self._components) def __repr__ (self ): components = reprlib.repr (self._components) components = components[components.find('[' ):-1 ] return 'Vector({})' .format (components) def __len__ (self ): return len (self._components) def __getitem__ (self, index ): cls = type (self) if isinstance (index, slice ): return cls(self._components[index]) elif isinstance (index, numbers.Integral): return self._components[index] else : msg = '{cls.__name__} indices must be integers' raise TypeError(msg.format (cls=cls)) vec = Vector(i for i in range (10 )) print(vec[1 :3 ])
总结:
Python中在切片或者索引的时候都会走__getitem__方法,对于切片来说会自动将输入范围定义为slice对象,通过解析此slice对象,可以获得正确的索引.