许可优化
许可优化
产品
产品
解决方案
解决方案
服务支持
服务支持
关于
关于
软件库
当前位置:服务支持 >  软件文章 >  Fluent Python第二版:切片(Slice)详解

Fluent Python第二版:切片(Slice)详解

阅读数 3
点赞 0
article_banner

Pyhton中序列类型支持切片功能,比如list:

>>> numbers = [1, 2, 3, 4, 5]>>> numbers[1:3]

[2, 3]

tuple也是序列类型,同样支持切片。

(一)我们是否可以使自定义类型支持切片呢?

在Python中创建功能完善的序列类型不需要使用继承,只要实现符合序列协议的方法就可以,Python的序列协议需要__len__, __getitem__两个方法,比如如下的Vector类:

from array importarrayclassVector:

type_code= 'd'

def __init__(self, compoments):

self.__components =array(self.type_code, compoments)def __len__(self):return len(self.__components)def __getitem__(self, index):return self.__components[index]

我们在控制台查看下切片功能:

>>> v1 = Vector([1, 2, 3])>>> v1[1]2.0

>>> v1[1:2]

array('d', [2.0])

在这里我们将序列协议委托给self.__compoments(array的实例),只需要实现__len__和__getitem__,就可以支持切片功能了。

(二)那么Python的切片工作原理又是怎样的呢?

我们通过一个简单的例子来查看slice的行为:

classMySequence:def __getitem__(self, index):return index

>>> s1 =MySequence()>>> s1[1]1

>>> s1[1:4]

slice(1, 4, None)>>> s1[1:4:2]

slice(1, 4, 2)>>> s1[1:4:2, 7:9]

(slice(1, 4, 2), slice(7, 9, None))

我们看到:

(1)输入整数时,__getitem__返回的是整数

(2)输入1:4表示法时,返回的slice(1, 4, None)

(3)输入1:4:2表示法,返回slice(1, 4, 2)

(4)[]中有逗号,__getitem__收到的是元组

现在我们来仔细看看slice本身:

>>>slice

>>>dir(slice)

['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge

__','__getattribute__','__gt__','__hash__','__init__','__init_subclass__','__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr_

_','__setattr__','__sizeof__','__str__','__subclasshook__','indices', 'star

t', 'step', 'stop']

我们看到了熟悉的start, stop, step属性,还有一个不熟悉的indices,用help查看下(Pyhon的控制台是很有价值的工具,我们常常使用dir,help命令获得帮助):

Help on method_descriptor:

indices(...)

S.indices(len)->(start, stop, stride)

Assuming a sequence of length len, calculate the startandstop

indices,andthe stride length of the extended slice described by

S. Out of bounds indices are clippedina manner consistent with the

handling of normal slices.

这里的indices能用于优雅的处理缺失索引和负数索引,以及长度超过目标序列长度的切片,这个方法会整顿输入的slice元组,把start, stop, step都变成非负数,且落在指定长度序列的边界内:

比如:

>>> slice(None, 10, 2).indices(5) #目标序列长度为5,自动将stop整顿为5

(0, 5, 2)>>> slice(-1, None, None).indices(5) #将start = -1, stop = None , step = None 整顿为(4, 5, 1)

(4, 5, 1)

如果没有底层序列作为代理,使用这个方法能节省大量时间

上面了解了slice的工作原理,我们使用它重新实现Vector类的__getitem__方法:

from array importarrayfrom numbers importIntegralclassVector:

type_code= 'd'

def __init__(self, compoments):

self.__components =array(self.type_code, compoments)def __len__(self):return len(self.__components)def __getitem__(self, index):

cls=type(self)ifisinstance(slice, index):return cls(self.__components[index]) #使用cls的构造方法返回Vector的实例

elifisinstance(Integral, index):return self.__components[index]else:raise TypeError("{} indices must be integers or slices".format(cls))


免责声明:本文系网络转载或改编,未找到原创作者,版权归原作者所有。如涉及版权,请联系删

相关文章
技术文档
QR Code
微信扫一扫,欢迎咨询~
customer

online

联系我们
武汉格发信息技术有限公司
湖北省武汉市经开区科技园西路6号103孵化器
电话:155-2731-8020 座机:027-59821821
邮件:tanzw@gofarlic.com
Copyright © 2023 Gofarsoft Co.,Ltd. 保留所有权利
遇到许可问题?该如何解决!?
评估许可证实际采购量? 
不清楚软件许可证使用数据? 
收到软件厂商律师函!?  
想要少购买点许可证,节省费用? 
收到软件厂商侵权通告!?  
有正版license,但许可证不够用,需要新购? 
联系方式 board-phone 155-2731-8020
close1
预留信息,一起解决您的问题
* 姓名:
* 手机:

* 公司名称:

姓名不为空

姓名不为空

姓名不为空
手机不正确

手机不正确

手机不正确
公司不为空

公司不为空

公司不为空