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. 在 Oracle Linux 6.5 上安装 Oracle 11g 单实例数据库

    Checking the Hardware Requirements 系统必须满足下面最小的硬件要求 Memory Requirements Minimum: 1 GB of RAMRecommend ...

  2. mysql 5.7设置密码无效

    我现在MySQL的版本时8.0.12,以前一直没有给MySQL设置密码. 今天因为需要,给MySQL设置,密码,但是上网搜了好久.....命令都不对.最后搜到csdn的Bpazy大佬的博客.他使用5. ...

  3. 使用ant design组件时,Select设置mode="multiple"或mode="tags"时遇到问题:Uncaught Error: must set key for <rc-animate> children

    import {Select} from 'antd'; <Select className={styles.edit_area_dialog_table_select_input_layout ...

  4. MySQL----MySQL数据库入门----第四章 单表查询

    select [distinct] * | 字段1,字段2,字段3... from 表名 [where 条件表达式] [group by 字段名] [having 条件表示式] [order by 字 ...

  5. 最新学习springboot 配置注解

    一.概述      Spring Boot设计目的是用来简化新Spring应用的初始搭建以及开发过程.Spring Boot并不是对Spring功能上的增强,而是提供了一种快速使用Spring的方式. ...

  6. [译文]程序员能力矩阵 Programmer Competency Matrix

    注意:每个层次的知识都是渐增的,位于层次n,也蕴涵了你需了解所有低于层次n的知识. 计算机科学 Computer Science   2n (Level 0) n2 (Level 1) n (Leve ...

  7. 4. HTML表单标签

    表单是网页中最常见的元素,也是用户和我们交互的重要手段,在网站中的登录.注册.信息更新这些功能都是依赖表单实现的.在HTML中对于表单提供了一系列的标签,即输入框.下拉框.按钮.文本域,如下是一个最常 ...

  8. Go 学习之路:异常处理defer,panic,recover

    Go没有像Java那样的异常机制,它不能抛出异常.因为设计者们认为,将异常与控制结构混在一起容易使得代码变得混乱.于是乎引入Exception处理: defer,panic,recover; 简单描述 ...

  9. 20155203 2016-2017-2《Java程序设计》课程总结

    目录 一.每周作业链接汇总 自认为写得最好一篇博客是?为什么? 作业中阅读量最高的一篇博客是?谈谈经验 作业中与师生交互最多的一篇博客是?谈谈收获 二.实验报告链接汇总 三.代码托管链接 四.课堂项目 ...

  10. QStackedWidget 与 QStackedLayout 的用法区别

    import sys from PyQt5 import QtWidgets, QtCore class MyWidget(QtWidgets.QWidget): def __init__(self, ...