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节时,有一个关于内存视图的例子,当时看的一知半解,后来查了一些资料,现在总结一下,以备后续查询: 示例复述 添加了一些额外的代码,便 ...
随机推荐
- linux 学习第十五天(vsftpd配置)
一.vstapd配置 vsftpd 服务(a.匿名公开 b.系统本地账户验证c.虚拟专用用户验证) iptables -F (清空防火墙) service iptables save (保存防火墙 ...
- Redis 4.0.X版本reshard出现错误的解决办法
原文链接:https://my.oschina.net/juluking/blog/1606222 原作者的版本是Redis 4.0.6,我的版本是4.0.8,所以猜测是否所有4.0.x版本都有此问题 ...
- Home Assistant系列 -- 接入手机摄像头做实时监控和人脸识别
准备一部废旧(土豪忽略,主要是穷)的.摄像头还是好的手机做监控设备,(Android 和iPhone都行)当Home Assistant 获得实时的视频流后,可以接入各种图像处理组件完成人脸识别,动作 ...
- conda与pip的关系
最近在搭建平台的时候,遇到了conda,具体尝试使用之后觉得conda还是非常好用的.他会交代清楚相互有依赖的包是什么,确认之后才会执行指令.要比pip好很多. 普通按照python 的时候一般都是自 ...
- 对Prolog的感想和我写的一些教程
我第一次见到Prolog这门独特的编程语言是在<七周七语言(Seven Languages in Seven Weeks)>中看到的.<七周七语言>名字看起来与市面上什么< ...
- 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 ...
- 20155320 《Java程序设计》实验三 敏捷开发与XP实践
20155320 <Java程序设计>实验三 敏捷开发与XP实践 实验内容 XP基础 XP核心实践 相关工具 (一)研究一下Code菜单 具体内容: 在IDEA中使用工具(Code-> ...
- PostgreSQL的streaming replication
磨砺技术珠矶,践行数据之道,追求卓越价值回到上一级页面: PostgreSQL集群方案相关索引页 回到顶级页面:PostgreSQL索引页[作者 高健@博客园 luckyjackgao@gm ...
- Spring Boot:Caused by: org.apache.ibatis.binding.BindingException: Parameter 'deptId' not found.
1. 错误信息描述 在使用Spring Boot + Mybaits从前台向后台提交数据时,控制台报出该错误信息 2. 报错原因 在dao接口中,该方法拥有两个参数,Mybaits无法区分这两个参数 ...
- .NET Core中使用RabbitMQ正确方式
.NET Core中使用RabbitMQ正确方式 首先甩官网:http://www.rabbitmq.com/ 然后是.NET Client链接:http://www.rabbitmq.com/dot ...