我是靠谱客的博主 寂寞狗,最近开发中收集的这篇文章主要介绍fluent python 2nd edition_Fluent Python: Slice,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

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

最后

以上就是寂寞狗为你收集整理的fluent python 2nd edition_Fluent Python: Slice的全部内容,希望文章能够帮你解决fluent python 2nd edition_Fluent Python: Slice所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(57)

评论列表共有 0 条评论

立即
投稿
返回
顶部