序列修改,散列和切片

  • 基本序列协议:Basic sequence protocol: __len__ and __getitem__

本章通过代码讨论一个概念: 把protocol当成一个正式接口。协议概念和鸭子类型的关系。当创建自定义类型时,它的实际影响。


Vector类,一个自定义的序列类型

我们的实现Vector的策略是使用composition(组合),而不是继承。


10.3 序列和鸭子类型

协议是非正式的接口,只在文档内定义,在代码中不定义。

例如,序列协议在Python只需要__len__, __getitem__方法。任何类只要实现了这2个方法,它的实例就能当序列用。

import collections
Card = collections.namedtuple('Card', ['rank', 'suit'])
class FrenchDeck:
ranks = [str(n) for n in range(2, 11)] + list('JQKA')
suits = 'spades diamonds clubs hearts'.split() def __init__(self):
self._cards = [Card(rank, suit) for suit in self.suits
for rank in self.ranks] def __len__(self):
return len(self._cards) def __getitem__(self, position):
return self._cards[position]
>>> import linshi
>>> d = linshi.FrenchDeck()
>>> d
<linshi.FrenchDeck object at 0x1041796d0>
>>> len(d)
52
>>> d[0]
Card(rank='', suit='spades')

因为在FrenchDeck类中定义了序列协议的2个方法。所以它的实例就能使用序列类型的2个方法。

即使FrenchDeck类是Object的子类,但因为实现了序列协议,就可以把它当成一个序列类型。

这就是鸭子类型。拥有鸭子的行为,那么就把它当成鸭子。

protocols是非正式的非强制的,所以可以只实现一个协议的部分。

10.4可切片的序列

__getitem__实现了切片功能:

>>> d[0:2]
[Card(rank='', suit='spades'), Card(rank='', suit='spades')]

⚠️

但是,返回的是一个list,而不是FrenchDeck实例。因此就不能使用FrenchDeck的其他实例方法。

再考虑到那些内置序列类型,切片后返回的都是一个新的原本类型的实例,而不是其他类型。

所以,基于以上2点考虑,有时,根据需要,我们需要优化__getitem__方法中的代码,让返回值是原类的实例。

10.4.1 How Slicing Works

这是书中一个例子:

>>> class MySeq:
... def __getitem__(self, index):
... return index
...
>>> s = MySeq()
>>> s
<__main__.MySeq object at 0x104ea16d0>
>>> s[1]
1
>>> s[2]
2
>>> s[1:4]
slice(1, 4, None)
>>> s[1:4:1]
slice(1, 4, 1)
>>> s[1:4:2]
slice(1, 4, 2)
>>> s[1:4:2, 9]
(slice(1, 4, 2), 9)
>>> s[1:4:2, 7:9]
(slice(1, 4, 2), slice(7, 9, None))

本例子使用__getitem__直接返回传给它的值。

s[1:2]使用切片返回的是一个切片对象。因此s[1:2]传递给__getitem__的就是一个切片对象。

而,如果[]中有逗号,则返回的是一个tuple。即__getitem__接受到的是一个元祖。元祖可以包括多个切片。

再看一下slice类本身, 如何处理切片?

>>> slice
<class 'slice'>
# 为了省事,截取最后的属性
>>> dir(slice)[-4:]
['indices', 'start', 'step', 'stop']

这里有一个属性indices,  其实是index的复数型。

使用: help(slice.indices)可以得到相关解释。

indices(...)
S.indices(len) -> (start, stop, stride)

S代表一个slice对象。参数len代表原来要被切片的对象的长度。这是个内部方法。

被切片的对象,如:

"abcde"[:10:2], 但"abcde"的长度只有5,索引end = 10,超出了"abcde"的长度范围。因此会内部调用indices,处理超出边界的索引。

因此,"abcde"[:10:2]就会被内部处理变成"abcde"[0:5:2]。

>>> "abcde"[0:10:2]
  1. Python内部处理时,会生成一个slice(0, 10, 2),
  2. 然后使用slice(0, 10, 2).indices(len("abcde"))得到(0,5,2),即start, end ,stride三个slice属性。
  3. 最后调用"abcde"[0:5:2]得到切片的字符串"ace"

小结:

my_seq[a:b:c]背后的工作原理,就是创建slice(a, b, c)对象,然后交给__getitem__方法进行后续处理。返回符合Python风格的自定义类的实例。


后面的章节未阅读。

《流畅的Python》 Sequence Hacking, Hashing and Slicing(没完成)的更多相关文章

  1. [读书笔记]流畅的Python(Fluent Python)

    <流畅的Python>这本书是图灵科技翻译出版的一本书,作者Luciano Ramalho. 作者从Python的特性角度出发,以Python的数据模型和特殊方法为主线,主要介绍了pyth ...

  2. 《流畅的python》读书笔记

    流畅的python 第1章 python数据模型 ---1.1 一摞Python风格的纸牌 特殊方法,即__method__,又被称为魔术方法(magic method)或者双下方法(dunder-m ...

  3. 流畅的python(笔记)

    流畅的python中有很多奇技淫巧,整本书都在强调如何最大限度地利用Python 标准库.介绍了很多python的不常用的数据类型.操作.库等,对于入门python后想要提升对python的认识应该有 ...

  4. 流畅的python 对象引用 可变性和垃圾回收

    对象引用.可变性和垃圾回收 变量不是盒子 人们经常使用“变量是盒子”这样的比喻,但是这有碍于理解面向对象语言中的引用式变量.Python 变量类似于 Java 中的引用式变量,因此最好把它们理解为附加 ...

  5. 《流畅的Python》一副扑克牌中的难点

    1.现在在看<流畅的Python>这本书,看了三页就发现,这本书果然不是让新手来入门的,一些很常见的知识点能被这个作者玩出花来, 唉,我就在想,下面要分析的这些的代码,就算我费劲巴拉的看懂 ...

  6. 《流畅的Python》Object References, Mutability, and Recycling--第8章

    Object References, Mutability, and Recycling 本章章节: Variables Are Not Boxes identity , Equality ,  Al ...

  7. 《流畅的Python》 第一部分 序章 【数据模型】

    流畅的Python 致Marta,用我全心全意的爱 第一部分 序幕 第一章 Python数据模型 特殊方法 定义: Python解释器碰到特殊句法时,使用特殊方法激活对象的基本操作,例如python语 ...

  8. SyntaxError: Non-UTF-8 code starting with '\xbb' in file D:\流畅学python\ex32.py on line 1, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details

    1. 报错如下: SyntaxError: Non-UTF-8 code starting with '\xd3' in file D:\流畅学python\ex34.py on line 4, bu ...

  9. 《流畅的Python》Data Structures--第2章序列array

    第二部分 Data Structure Chapter2 An Array of Sequences Chapter3 Dictionaries and Sets Chapter4 Text vers ...

随机推荐

  1. Mysql统计每年每个月的数据——详细教程

    Mysql统计每年每个月的数据(前端页面统计图实现) 最终想实现的效果图,在这里就不多废话了,直接上效果图,由于测试数据有几个月是为0的,所以数据图看着会有点怪怪. 接下来是数据库的两个表,这里直接给 ...

  2. 【leetcode算法-中等】2. 两数相加

    [题目描述] 给出两个 非空 的链表用来表示两个非负的整数.其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字. 如果,我们将这两个数相加起来,则会返回一个新的链表 ...

  3. The Select mechanism in linux for block mechanism

    Today, some one mention theknowledge of Select Mechanism. It's better to konw something about it ! O ...

  4. 微信小程序session_key和access_token傻傻分不清楚

    之前一直对着文档使用特定接口, 今天闲来仔细研究一下各个接口的使用, 然后发现了session_key和access_token两个关键字意义有点重复啊? 目测都是某种钥匙来打开一扇门的, 那为什么有 ...

  5. Linux安装 PostgreSQL

    1.在线安装 yum install postgresql-server -y 2.初始化数据库 service postgresql initdb 3.设置自动启动 hkconfig postgre ...

  6. Python class and object

    # Python继承 class Person(object): """人""" def __init__(self, name, age) ...

  7. scrapy 爬取纵横网实战

    前言 闲来无事就要练练代码,不知道最近爬取什么网站好,就拿纵横网爬取我最喜欢的雪中悍刀行练手吧 准备 python3 scrapy 项目创建: cmd命令行切换到工作目录创建scrapy项目  两条命 ...

  8. 在Yii2中集成Markdown编辑器

    安装命令: composer require ijackua/yii2-lepture-markdown-editor-widget:dev-master 可能会遇到的问题 如果在下载依赖包的过程中出 ...

  9. S03_CH05_AXI_DMA_HDMI图像输出

    S03_CH05_AXI_DMA_HDMI图像输出 5.1概述 本课程是在前面课程基础上添加HDMI IP 实现HDMI视频图像的输出.本课程出了多了HDMI输出接口,其他内容和<S03_CH0 ...

  10. Form key length limit 2048 exceeded ,提交数据时,数据的键过长 或者是上传文件过大

    在ASP.NET Core MVC中,文件的key 默认最大为2048,文件上传的最大上传文件默认为20MB,如果我们想上传一些比较大的文件,就不知道怎么去设置了,没有了Web.Config我们应该如 ...