如何使用Python内置切片对象?

84 投票
6 回答
58378 浏览
提问于 2025-04-16 05:21

我知道Python里有一种很酷的切片方法:l1[start:stop:step]

那内置的函数slice有什么用呢?
我该怎么用它呢?

6 个回答

8

在编程中,有时候我们需要处理一些数据,比如从一个地方获取信息,然后把这些信息存储到另一个地方。这个过程就像把水从一个桶倒到另一个桶一样。

有些时候,我们会遇到一些问题,比如数据的格式不对,或者我们想要的数据没有被正确地获取到。这就需要我们仔细检查每一步,确保每个环节都没有出错。

另外,编程中还有很多工具和库可以帮助我们更方便地处理这些数据。就像在厨房里,我们有刀、锅、碗等工具来帮助我们做饭一样。

总之,处理数据的过程需要耐心和细心,确保每一步都正确,这样才能得到我们想要的结果。

>>> 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)),)
>>>
41

在一个序列后面加上方括号,里面的内容决定了是索引还是切片:

>>> "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__ 方法时,你需要检查索引参数,以确定它是一个 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 对象有三个属性: startstopstep,还有一个方法: indices,这个方法需要一个参数,即对象的长度,返回一个三元组: (start, stop, step)

112

你可以通过调用slice函数来创建一个切片,使用的字段和你在写[start:end:step]这种格式时是一样的:

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('')

# or this same code using itemgetter, to make a function that
# extracts all slices from a string into a tuple of values
import operator
rec_reader = operator.itemgetter(*fieldslices)
for rec in data:
    for field, field_value in zip(fields, rec_reader(rec)):
        print("{} : {}".format(field, field_value))
    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

撰写回答