内置函数slice
的用途是什么?如何使用它?
我知道Pythonic切片的直接方式 - l1[start:stop:step]
。我想知道我是否有切片对象,然后如何使用它?
答案 0 :(得分:84)
通过使用与[start:end:step]表示法相同的字段调用slice来创建切片:
sl = slice(0,4)
要使用切片,只需将其作为索引传递给列表或字符串:
>>> s = "ABCDEFGHIJKL"
>>> sl = slice(0,4)
>>> print(s[sl])
'ABCD'
假设您有一个固定长度文本字段的文件。您可以定义切片列表,以便轻松地从此文件中的每个“记录”中提取值。
data = """\
0010GEORGE JETSON 12345 SPACESHIP ST HOUSTON TX
0020WILE E COYOTE 312 ACME BLVD TUCSON AZ
0030FRED FLINTSTONE 246 GRANITE LANE BEDROCK CA
0040JONNY QUEST 31416 SCIENCE AVE PALO ALTO CA""".splitlines()
fieldslices = [slice(*fielddef) for fielddef in [
(0,4), (4, 21), (21,42), (42,56), (56,58),
]]
fields = "id name address city state".split()
for rec in data:
for field,sl in zip(fields, fieldslices):
print("{} : {}".format(field, rec[sl]))
print('')
打印:
id : 0010
name : GEORGE JETSON
address : 12345 SPACESHIP ST
city : HOUSTON
state : TX
id : 0020
name : WILE E COYOTE
address : 312 ACME BLVD
city : TUCSON
state : AZ
id : 0030
name : FRED FLINTSTONE
address : 246 GRANITE LANE
city : BEDROCK
state : CA
id : 0040
name : JONNY QUEST
address : 31416 SCIENCE AVE
city : PALO ALTO
state : CA
答案 1 :(得分:32)
序列后面的方括号表示索引或切片,具体取决于括号内的内容:
>>> "Python rocks"[1] # index
'y'
>>> "Python rocks"[1:10:2] # slice
'yhnrc'
这两种情况都由序列的__getitem__()
方法处理(如果在等号的左侧,则为__setitem__()
。)索引或切片作为单个参数传递给方法,Python的做法是将切片表示法(在本例中为1:10:2
)转换为切片对象:slice(1,10,2)
。
因此,如果您要定义自己的类序列或覆盖另一个类的__getitem__
或__setitem__
或__delitem__
方法,则需要测试index参数以确定它是否为是int
或slice
,并相应处理:
def __getitem__(self, index):
if isinstance(index, int):
... # process index as an integer
elif isinstance(index, slice):
start, stop, step = index.indices(len(self)) # index is a slice
... # process slice
else:
raise TypeError("index must be int or slice")
slice
个对象有三个属性:start
,stop
和step
,以及一个方法:indices
,它采用一个参数,长度对象,并返回一个3元组:(start, stop, step)
。
答案 2 :(得分:7)
>>> class sl:
... def __getitem__(self, *keys): print keys
...
>>> s = sl()
>>> s[1:3:5]
(slice(1, 3, 5),)
>>> s[1:2:3, 1, 4:5]
((slice(1, 2, 3), 1, slice(4, 5, None)),)
>>>
答案 3 :(得分:3)
slice
函数返回slice objects。 Slice对象是Python的内部类型之一,它们针对读取性能进行了优化 - 它们的所有属性都是只读的。
如果希望更改默认行为,则更改slice
可能很有用。例如,lxml
使用切片表示法来访问DOM元素(但是,我还没有确认他们是如何做到这一点的。)
答案 4 :(得分:1)
在尝试回答Subset a string based on variable时,我回想起numpy在语法上定义切片对象的方法不错:
>>> import numpy as np
>>> s = "The long-string instrument is a musical instrument in which the string is of such a length that the fundamental transverse wave is below what a person can hear as a tone."
>>> z = np.s_[18:26] # in this case same as slice(18, 26, None)
>>> s[z]
'strument'
这里解决的问题是如何将切片存储在变量中以备后用,而np.s_
允许这样做。是的,它不是内置的,但由于该原始问题已在此处重定向,因此我的回答也属于此处。另外,numpy是向Python IIRC中添加如此高级的切片功能的原因之一。
更复杂的“切片”示例:
>>> data = np.array(range(6)).reshape((2, 3))
>>> z = np.s_[:1, 1:2]
>>> data[z]
array([[1]])
>>> data
array([[0, 1, 2],
[3, 4, 5]])
>>> z
(slice(None, 1, None), slice(1, 2, None))
其中z现在是切片的元组。
答案 5 :(得分:0)
Slice对象使您可以以编程方式生成和操作切片。特别是对于多维numpy数组,尤其是如果您事先不知道维数时,您可能希望即时构造切片以指定所需的轴或维。
import numpy as np
dimension = np.random.randint(10) # Might have up to 10 dimensions
shape = []
for d in range(dimension):
shape.append(np.random.randint(10))
zz = np.random.rand(tuple(shape))
print(zz)
>>> array([[0.68379351, 0.50854469, 0.64578775, 0.73441699, 0.28977396],
[0.88797164, 0.81603025, 0.63978659, 0.22677299, 0.93455738],
[0.0892855 , 0.28048706, 0.04262895, 0.9353467 , 0.13062249],
[0.88561035, 0.93378367, 0.12124208, 0.25600301, 0.96035638]])
在这里,我们的数据最终是二维的(4 x 5),但是并不能保证这一点。您将如何从zz
请求切片?
一个问题是我无法操纵Python的切片符号。切片操作之外的语法无效。
my_slice = 2:3:1
>>> SyntaxError: Invalid Syntax
如果我可以循环构建所需的确切切片请求,该如何构建字符串呢?那不是很好吗?我的意思是,请确保您可以使用字符串来执行此操作,但这很麻烦,并且需要eval
。
your_slice_definitions = [(2,3,1), *[(None, None, None)]*(zz.ndim - 1)]
my_slice_str = ""
for slice_start, slice_end, slice_step in your_slice_definitions:
my_slice_str += "{}:{}:{},".format(slice_start, slice_end, slice_step)
eval("zz["+my_slice_str+"])
所以我们在这里:slice
对象可让您执行此操作。您可以动态地组装它们的列表和元组,将它们作为函数参数传递,对其进行排序,对其进行随机排序等等。
my_slices = []
for slice_start, slice_end, slice_step in your_slice_definitions:
my_slices += slice(slice_start, slice_end, slice_step)
print(zz[my_slices])
>>> array([[0.0892855 , 0.28048706, 0.04262895, 0.9353467 , 0.13062249]])