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

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

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

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

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

from array import array

class Vector:
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的行为:

class MySequence:
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
<class '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 start and stop
indices, and the stride length of the extended slice described by
S. Out of bounds indices are clipped in a 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 import array
from numbers import Integral class Vector:
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)
if isinstance(slice, index):
return cls(self.__components[index]) # 使用cls的构造方法返回Vector的实例
elif isinstance(Integral, index):
return self.__components[index]
else:
raise TypeError("{} indices must be integers or slices".format(cls))

Fluent Python: Slice的更多相关文章

  1. 学习笔记之Fluent Python

    Fluent Python by Luciano Ramalho https://learning.oreilly.com/library/view/fluent-python/97814919462 ...

  2. 「Fluent Python」今年最佳技术书籍

    Fluent Python 读书手记 Python数据模型:特殊方法用来给整个语言模型特殊使用,一致性体现.如:__len__, __getitem__ AOP: zope.inteface 列表推导 ...

  3. Python slice() 函数

    Python slice() 函数  Python 内置函数 描述 slice() 函数实现切片对象,主要用在切片操作函数里的参数传递. 语法 slice 语法: class slice(stop) ...

  4. Fluent Python: memoryview

    关于Python的memoryview内置类,搜索国内网站相关博客后发现对其解释都很简单, 我觉得学习一个新的知识点一般都要弄清楚两点: 1, 什么时候使用?(也就是能解决什么问题) 2,如何使用? ...

  5. Python深入学习之《Fluent Python》 Part 1

    Python深入学习之<Fluent Python> Part 1 从上个周末开始看这本<流畅的蟒蛇>,技术是慢慢积累的,Python也是慢慢才能写得优雅(pythonic)的 ...

  6. Fluent Python: Classmethod vs Staticmethod

    Fluent Python一书9.4节比较了 Classmethod 和 Staticmethod 两个装饰器的区别: 给出的结论是一个非常有用(Classmethod), 一个不太有用(Static ...

  7. Fluent Python: @property

    Fluent Python 9.6节讲到hashable Class, 为了使Vector2d类可散列,有以下条件: (1)实现__hash__方法 (2)实现__eq__方法 (3)让Vector2 ...

  8. Fluent Python: Mutable Types as Parameter Defaults: Bad Idea

    在Fluent Python一书第八章有一个示例,未看书以先很难理解这个示例运行的结果,我们先看结果,然后再分析问题原因: 定义了如下Bus类: class Bus: def __init__(sel ...

  9. 《Fluent Python》---一个关于memoryview例子的理解过程

    近日,在阅读<Fluent Python>的第2.9.2节时,有一个关于内存视图的例子,当时看的一知半解,后来查了一些资料,现在总结一下,以备后续查询: 示例复述 添加了一些额外的代码,便 ...

随机推荐

  1. linux 学习第十五天(vsftpd配置)

    一.vstapd配置 vsftpd 服务(a.匿名公开 b.系统本地账户验证c.虚拟专用用户验证) iptables -F  (清空防火墙) service iptables save  (保存防火墙 ...

  2. Redis 4.0.X版本reshard出现错误的解决办法

    原文链接:https://my.oschina.net/juluking/blog/1606222 原作者的版本是Redis 4.0.6,我的版本是4.0.8,所以猜测是否所有4.0.x版本都有此问题 ...

  3. Home Assistant系列 -- 接入手机摄像头做实时监控和人脸识别

    准备一部废旧(土豪忽略,主要是穷)的.摄像头还是好的手机做监控设备,(Android 和iPhone都行)当Home Assistant 获得实时的视频流后,可以接入各种图像处理组件完成人脸识别,动作 ...

  4. conda与pip的关系

    最近在搭建平台的时候,遇到了conda,具体尝试使用之后觉得conda还是非常好用的.他会交代清楚相互有依赖的包是什么,确认之后才会执行指令.要比pip好很多. 普通按照python 的时候一般都是自 ...

  5. 对Prolog的感想和我写的一些教程

    我第一次见到Prolog这门独特的编程语言是在<七周七语言(Seven Languages in Seven Weeks)>中看到的.<七周七语言>名字看起来与市面上什么< ...

  6. 10 Quality Free Flat Icon Sets for Your Designs

    Subscribe It’s clear that flat design has gained great popularity in recent years. This is hardly su ...

  7. 20155320 《Java程序设计》实验三 敏捷开发与XP实践

    20155320 <Java程序设计>实验三 敏捷开发与XP实践 实验内容 XP基础 XP核心实践 相关工具 (一)研究一下Code菜单 具体内容: 在IDEA中使用工具(Code-> ...

  8. PostgreSQL的streaming replication

    磨砺技术珠矶,践行数据之道,追求卓越价值回到上一级页面: PostgreSQL集群方案相关索引页     回到顶级页面:PostgreSQL索引页[作者 高健@博客园  luckyjackgao@gm ...

  9. Spring Boot:Caused by: org.apache.ibatis.binding.BindingException: Parameter 'deptId' not found.

    1. 错误信息描述 在使用Spring Boot + Mybaits从前台向后台提交数据时,控制台报出该错误信息 2. 报错原因 在dao接口中,该方法拥有两个参数,Mybaits无法区分这两个参数 ...

  10. .NET Core中使用RabbitMQ正确方式

    .NET Core中使用RabbitMQ正确方式 首先甩官网:http://www.rabbitmq.com/ 然后是.NET Client链接:http://www.rabbitmq.com/dot ...