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

2025-03-20 08:47:00
admin
原创
29
摘要:问题描述:我知道 Pythonic 切片:l1[start:stop:step]。内置函数有什么用slice? 如何使用它?解决方案 1:你可以通过调用切片来创建一个切片,使用和执行 [start:end:step] 符号时相同的字段:sl = slice(0,4) 要使用切片,只需将其作为列表或字符串的索...

问题描述:

我知道 Pythonic 切片:l1[start:stop:step]

内置函数有什么用slice

如何使用它?


解决方案 1:

你可以通过调用切片来创建一个切片,使用和执行 [start:end:step] 符号时相同的字段:

sl = slice(0,4)

要使用切片,只需将其作为列表或字符串的索引传递即可:

>>> s = "ABCDEFGHIJKL"
>>> sl = slice(0,4)
>>> print(s[sl])
'ABCD'

假设您有一个固定长度的文本字段文件。您可以定义一个切片列表,以便轻松从此文件中的每个“记录”中提取值。

data = """\n0010GEORGE 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

解决方案 2:

序列后面的方括号表示根据括号内的内容进行索引或切片:

>>> "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__方法,则需要测试索引参数以确定它是否是intslice,并进行相应的处理:

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,它接受一个参数,即对象的长度,并返回一个 3 元组:(start, stop, step)

解决方案 3:

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

解决方案 4:

slice函数返回切片对象。切片对象是 Python 的内部类型之一,针对读取性能进行了优化 - 它们的所有属性都是只读的。

如果希望更改默认行为,则修改slice可能会很有用。例如,lxml使用切片符号访问 DOM 元素(但是,我自己还没有确认他们是如何做到这一点的)。

解决方案 5:

在尝试回答根据变量对字符串进行子集时,我记得 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 的原因之一,如果我没记错的话。

更复杂的“切片”示例:

>>> 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 现在是切片的元组。

解决方案 6:

切片对象可让您以编程方式生成和操作切片。特别是对于多维 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×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]])
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2482  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1533  
  PLM(产品生命周期管理)项目对于企业优化产品研发流程、提升产品质量以及增强市场竞争力具有至关重要的意义。然而,在项目推进过程中,范围蔓延是一个常见且棘手的问题,它可能导致项目进度延迟、成本超支以及质量下降等一系列不良后果。因此,有效避免PLM项目范围蔓延成为项目成功的关键因素之一。以下将详细阐述三大管控策略,助力企业...
plm系统   0  
  PLM(产品生命周期管理)项目管理在企业产品研发与管理过程中扮演着至关重要的角色。随着市场竞争的加剧和产品复杂度的提升,PLM项目面临着诸多风险。准确量化风险优先级并采取有效措施应对,是确保项目成功的关键。五维评估矩阵作为一种有效的风险评估工具,能帮助项目管理者全面、系统地评估风险,为决策提供有力支持。五维评估矩阵概述...
免费plm软件   0  
  引言PLM(产品生命周期管理)开发流程对于企业产品的全生命周期管控至关重要。它涵盖了从产品概念设计到退役的各个阶段,直接影响着产品质量、开发周期以及企业的市场竞争力。在当今快速发展的科技环境下,客户对产品质量的要求日益提高,市场竞争也愈发激烈,这就使得优化PLM开发流程成为企业的必然选择。缺陷管理工具和六西格玛方法作为...
plm产品全生命周期管理   0  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用