第四章:自定义序列类

1. Python中的序列该怎么理解?

有下标,有顺序,可以进行迭代,切片,相加等操作.

2. Python中的序列常见的通用操作

索引(index) 分片(slicing) 序列相加(拼接) 乘法(重复) 成员资格(in) 长度(len) max() min() 可以迭代
sorted enumerate zip filter map

3.Python中序列的常用分类

按照存放的类型不同:
容器序列
list , tuple , collections.deque
扁平序列
str, bytes,bytesarray,memoryview,array.array

容器序列和扁平序列的区别?
容器序列存放的是它们对任意类型对象的引用,而扁平序列存放的是值,而不是引用.换句话说,扁平序列是一段连续的内存空间.扁平序列只能存放单一的类型,并且还是基本的数据类型,例如:字符,字节,和数值这种类型的

按照是否可变的维度:
可变序列
list,collections.queue, array.array,bytearray,memoryview
不可变序列
tuple , str, bytes

4.序列的abc继承关系

下图展示了可变序列(MutableSequence)和不可变序列(Sequence)的差异,同时 也能看出前者从后者那里继承了一些方法。虽然内置的序列类型并不是直接从 Sequence 和 MutableSequence 这两个抽象基类(Abstract Base Class,ABC)继承而来的,但是了 解这些基类可以帮助我们总结出那些完整的序列类型包含了哪些功能。

5.序列类型的+, += ,和extend的区别?

+= 在序列中实际上调用的是iadd方法

    def __iadd__(self, values):
        self.extend(values)
        return self

extend()是通过遍历来实现添加元素的

def extend(self, values):
        'S.extend(iterable) -- extend sequence by appending elements from the iterable'
        for v in values:
            self.append(v)

注意: 序列的+ 号调用的是魔法方法__add__,两边必须是相同的类型.而+=调用的是extend方法,右边只要是一个可迭代的序列都可以的.

# encoding:utf-8
__author__ = 'Fioman'
__time__ = '2019/3/15 19:33'
from collections import abc
a = [1,2]
c = a + [3,4]
print(c)
c += (1,2) # 调用的是`iadd`里面调用的是extend.而extend使用的是for循环.
print(c)
# c = a + (1,2)  # 这里会报错,+号两边只能放相同的序列.

c.append([1,3])# 这里是将[1,3]列表,作为一个元素添加到列表的后边
c.extend([1,3]) # 这里是将[1,3]合并到原来的列表上.
# append是追加一个元素,extend是扩充列表.\
print(dir(c))

6.Python的切片

格式:

可切片对象[start:end:step]

1.start 表示切片的起始位置.如果不提供,默认是0.可以省略
2.end 表示切片的结束位置.如果不提供,默认是是对象长度,len(object).可以省略
3.step 表示步长,可以省略,默认是1.也可以说hi负数,当step省略的时候,第二个冒号可以省略.step也可以是负数

alist = [3,4,5,6,7,9,11,13,15,17]
print(alist[::]) # 返回包含原列表中所有元素的新列表
print(alist[::-1]) # 返回原列表的逆序排列
print(alist[::2]) # 返回原列表的偶数位数据
print(alist[1::2]) # 获取奇数位置的数据
print(alist[3:6]) # 指定切片的开始和结束位置
print(alist[0:100]) # 切片位置大于列表长度时,从列表尾部截断
print(alist[100:]) # 切片开始位置大于列表长度时,返回空列表
alist[len(alist):]=[9] # 在列表尾部增加元素
print(alist)
alist[:0] = [1,2] # 前面的0省略了,相当于是alist[0:0] = [1,2]
print(alist)      # 在列表的头部增加元素
alist[3:3] =[4] # 在列表中间插入元素
print(alist)
alist[:3] = [1,2] # 相当于是alist[0:3] = [1,2] 替换列表元素
alist[3:] = [4,5,6] # 替换元素,结果按照两边的最短元素来决定.
print(alist)
alist[:3] = []  # 删除列表中前三个元素
del alist[:3] # 切片元素连续
del alist[::2] # 隔一个删除一个,切片元素不连续

实现自定义的序列

# encoding:utf-8
__author__ = 'Fioman'
__time__ = '2019/3/17 9:42'
import numbers


class Group:
    # 支持切片操作
    def __init__(self, group_name, company_name, staffs):
        self.group_name = group_name
        self.company_name = company_name
        self.staffs = staffs

    def __reversed__(self):
        self.staffs.reverse()

    # 因为object[] 和 object[::]都会调动这个方法
    def __getitem__(self, item):
        # 取到class
        cls = type(self)
        if isinstance(item, slice):
            return cls(group_name=self.group_name, company_name=self.company_name,
                       staffs=self.staffs[item])
        if isinstance(item, numbers.Integral):
            return self.staffs[item]

    def __iter__(self):
        return iter(self.staffs)

    def __len__(self):
        return len(self.staffs)

    def __str__(self):
        return '组员有:{}'.format(self.staffs)

    def __contains__(self, item):
        if item in self.staffs:
            return True
        else:
            return False


staffs = ['fioman', '123', '456', '789']
group = Group('A', '大王', staffs=staffs)
sub_group = group[:2]
print(group)

if 'A' in group:  # 这里会调用__contains__魔法函数
    print('yes')

for item in group:
    print(item)

reversed(group) # 实际上是调用了__reversed__魔法函数
print(group)

7. 使用bisect来维护一个有顺序的序列,升序.其实就是向一个序列中添加元素之后使得这个序列是有序的.

bisect功能介绍
1. 插入一个元素,并且使用二分法进行排序,使得这个序列升序排列
2. 如果有相同元素,可以控制它的插入是在左边还是右边.默认是右边插入
3. 可以查看一个元素左插入位置,和右插入位置.默认是查询右边插入的位置

# encoding:utf-8
__author__ = 'Fioman'
__time__ = '2019/3/17 10:28'
import bisect

lst = [1,3,4,2,5,1]
# 使用bisect的前提是原来的序列必须是有序的
lst.sort()
print(bisect.bisect_right(lst,3)) # 4
print(bisect.bisect_left(lst,3)) # 3
bisect.insort(lst, 3)
bisect.insort(lst,6)
bisect.insort_left(lst,3) # 从3的位置插入
print(lst)

8. 什么时候我们不应该使用列表,而使用array

当存放的数据是单一数据时,我们最好使用array.因为array比list的效率要高.

array和list的区别?
1.array只能存放相同类型的数据,而list可以存放不同类型的对象.
2.array是一片连续的内存空间,而list里面的对象可能是存放在别处.

# encoding:utf-8
__author__ = 'Fioman'
__time__ = '2019/3/17 10:34'
import array
# array 就相当于是C语言的数组.
# array和list的一个重要区别,arr只能存放相当类型的数据.必须指定
# 而list可以存放不同的类型的对象
a = list
my_array = array.array('i') # 有符号的整型
my_array.append(1)
# my_array.append('abc') # 只能存放int类型的数据

9.列表推导式,生成器表达式,字典推导式,集合推导式

# encoding:utf-8
__author__ = 'Fioman'
__time__ = '2019/3/17 10:42'
# 列表推导式
# 1.提取出1-20之间的奇数
odd_list = []
for i in range(21):
    if i % 2 == 1:
        odd_list.append(i)
print(odd_list)

# 使用列表推导式
odd_list = [x for x in range(21) if x % 2 == 1]
print(odd_list)


# 列表推导式的格式
# [on True for x in iteralbe 条件表达式(过滤)]

# 逻辑复杂的情况
def handle_item(item):
    return item * item


odd_list = [handle_item(x) for x in range(21) if x % 2 == 1]
print(odd_list)
# 列表表达式的前面可以是一个函数,也可以是一个函数,但是不能是匿名函数

# 生成器表达式,将列表推导式的[]改成(),就变成了生成器表达式
gen = (x for x in range(21) if x % 2 == 1)
print(gen)  # <generator object <genexpr> at 0x000001CF1B01C8E0>
print(type(gen))  # <class 'generator'>
for item in gen:
    print(item)

# 字典推导式,颠倒key和value
my_dict = {'bob1': 22, 'bob3': 23, 'bob4': 5}

reversed_dict = {value: key for key, value in my_dict.items()}
print(reversed_dict)

# 集合推导式 set
# 如何将一个字典的key全部放到一个集合当中.
my_set = {key for key in my_dict.keys()}
# 也可以使用
my_set = set(my_dict.keys())
print(type(my_set))
print(my_set)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容

  • 《皮绳上的魂》里,作品中虚构的人物最终与描述他们的主人——作家相遇。这样的设计,基本上都是接受的声音,没有人说看不...
    姚寓泾阅读 220评论 0 0
  • 昨天参加了一个读书会,关于高效人士的7个习惯。 这本书实在是熟之又熟,直到熟透。然而在昨天,它又被赋予了新的意义。...
    一窗暮色薄光阅读 160评论 0 2
  • 某次错过 就开始慢慢忘记 忘记了 某一天 本应该做的事 也许 那时候想着 做一次寄存 却不想 哪一天之后 花正香 ...
    白色鸽子阅读 53评论 0 1