Fluent Python: Slice
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的更多相关文章
- 学习笔记之Fluent Python
Fluent Python by Luciano Ramalho https://learning.oreilly.com/library/view/fluent-python/97814919462 ...
- 「Fluent Python」今年最佳技术书籍
Fluent Python 读书手记 Python数据模型:特殊方法用来给整个语言模型特殊使用,一致性体现.如:__len__, __getitem__ AOP: zope.inteface 列表推导 ...
- Python slice() 函数
Python slice() 函数 Python 内置函数 描述 slice() 函数实现切片对象,主要用在切片操作函数里的参数传递. 语法 slice 语法: class slice(stop) ...
- Fluent Python: memoryview
关于Python的memoryview内置类,搜索国内网站相关博客后发现对其解释都很简单, 我觉得学习一个新的知识点一般都要弄清楚两点: 1, 什么时候使用?(也就是能解决什么问题) 2,如何使用? ...
- Python深入学习之《Fluent Python》 Part 1
Python深入学习之<Fluent Python> Part 1 从上个周末开始看这本<流畅的蟒蛇>,技术是慢慢积累的,Python也是慢慢才能写得优雅(pythonic)的 ...
- Fluent Python: Classmethod vs Staticmethod
Fluent Python一书9.4节比较了 Classmethod 和 Staticmethod 两个装饰器的区别: 给出的结论是一个非常有用(Classmethod), 一个不太有用(Static ...
- Fluent Python: @property
Fluent Python 9.6节讲到hashable Class, 为了使Vector2d类可散列,有以下条件: (1)实现__hash__方法 (2)实现__eq__方法 (3)让Vector2 ...
- Fluent Python: Mutable Types as Parameter Defaults: Bad Idea
在Fluent Python一书第八章有一个示例,未看书以先很难理解这个示例运行的结果,我们先看结果,然后再分析问题原因: 定义了如下Bus类: class Bus: def __init__(sel ...
- 《Fluent Python》---一个关于memoryview例子的理解过程
近日,在阅读<Fluent Python>的第2.9.2节时,有一个关于内存视图的例子,当时看的一知半解,后来查了一些资料,现在总结一下,以备后续查询: 示例复述 添加了一些额外的代码,便 ...
随机推荐
- iOS之UIButton扩大按钮的响应区域
在开发中有时会遇见设计图里按钮设计的特别小,这时会用到手动扩大UIButton的响应范围,下面有两个解决办法: 第一种方法:创建一个类目:UIButton+EnlargeTouchArea .h文件 ...
- 使用vue封装一个tab栏切换的左侧导航栏的公共组件
首先看最终效果图: 1.compent文件夹里添加tab文件夹,里面创建index.vue index.js index.css index.vue内的template部份代码如下:(最新更正:代码 ...
- js cookie使用
if (window.localStorage) { window.localStorage.setItem('cname', "cvalue"); }else{ setCooki ...
- GoogleMock初探(0)
在进行测试过程中,待测的类或者方法经常会依赖其他类或方法的实现.如果此时这些依赖还没有实现,则需要打桩.另外测试讲求独立,测试之间的互相依赖会导致测试最终混乱不堪. GoogleMock提供一套方法来 ...
- 模板——STL队列
C++ STL queue 容器优先队列&&队列 队列 #include<queue> #include<iostream> using namespace s ...
- Java实例 Part3:流程控制
目录 Example01:判断某一年是否为闰年 Example02:验证登录信息的合法性 Example03:判断用户输入月份的季节 Example04:使用while循环语句与自增运算符循环遍历数组 ...
- Python学习——编程语言介绍
开发语言 高级语言:基于C/汇编等封装的语言,如Python.Java.C#.PHP.Go.ruby.C++……生成字节码让C/汇编去识别 低级语言:直接让计算机底层能识别成机器码的语言(计算机再将机 ...
- 数据结构与算法之排序(1)冒泡排序 ——in dart
最经典的入门排序算法,冒泡排序,dart语言实现.数组仍然采用随机生成的数组,使用dart内置的List 的generate方法,排序前后分别打印出数组,以观察效果. import 'dart:mat ...
- 20155207JAVA第十二周课堂练习
20155207JAVA第十二周课堂练习 教材代码检查--P98 修改教材P98 Score2.java, 让执行结果数组填充是自己的学号 Arrays和String单元测试 在IDEA中以TDD的方 ...
- 20155316 实验四 《Android程序设计》
实验1 实验内容 Android Stuidio的安装测试: 参考<Java和Android开发学习指南(第二版)(EPUBIT,Java for Android 2nd)>第二十四章: ...