Python高级编程(24):什么时候我们不该使用列表?
尽管我们在大多情况之下喜欢使用列表,但是有的时候我们不该使用列表,而是转向使用更高级的Python内置的数据类型,这里主要说array和deque。
上面这个图片就是展示了Python中用C语言写的列表所具有的全部方法,我们从这就能知道所有的信息。前面说过列表是一种容器序列,可以存放不同数据类型的对象。这个数组array就只能存放指定类型的数据类型对象了。
123456789import array# array和list的一个重要区别, array只能存放指定的数据类型my_array = array.array("i") # 这里的i就表明这个数组就只能存放int类型的对象my_array.append(1) # 运行正常my_array.append("abc") # 运行报错# 报错内容: my_array.append("abc")TypeError: an integer is required (got type str)
参考文章:[ - ]:array文档
Python高级编程(22):实现可切片的对象
我们来看一段代码,注意一下这里的start和end指的都是索引号,不是值(如[3:6]就是指索引号为3/4/5的元素,索引号从0开始):
1234567891011121314151617181920212223242526# 模式[start:end:step]""" 其中,第一个数字start表示切片开始位置,默认为0; 第二个数字end表示切片截止(但不包含)位置(默认为列表长度); 第三个数字step表示切片的步长(默认为1)。 当start为0时可以省略,当end为列表长度时可以省略, 当step为1时可以省略,并且省略步长时可以同时省略最后一个冒号。 另外,当step为负整数时,表示反向切片,这时start应该比end的值要大才行。"""aList = [3, 4, 5, 6, 7, 9, 11, 13, 15, 17]print (aList[::]) # 返回包含原列表中所有元素的新列表print (aList[::-1]) # 返回包含原列表中所有元素的逆序列表prin ...
Python高级编程(23):bisect维护已排序序列
1234567891011121314151617181920import bisectfrom collections import deque# 用来处理已排序的序列,用来维持已排序的序列, 升序# 二分查找inter_list = deque()bisect.insort(inter_list, 3)bisect.insort(inter_list, 2)bisect.insort(inter_list, 5)bisect.insort(inter_list, 1)bisect.insort(inter_list, 6)print(bisect.bisect_left(inter_list, 3))# 学习成绩print(inter_list)# 输出结果:2deque([1, 2, 3, 5, 6])
我们只需要记住几点:1、bisect = bisect_right 和 insort = insort_right,而且insort 返回插入后的新列表,而bisect 则是返回在列表中的位置(索引号)。
具体的可以看这里:bisect——模块
Python高级编程(21):list中+、+=、extend的方法区别
我们知道在list中,有+、+=、和extend,但是它这3个的区别你知道么?
+:
1234567a = [1,2 ,3]c = a + [5,6,7]print(c)# 输出结果:[1, 2, 3, 5, 6, 7]
+=:
1234567a = [1,2 ,3]a += [5,6,7]print(a)# 输出结果:[1, 2, 3, 5, 6, 7]
你肯定会说这个没啥好说的,那么我们修改一下,将这个列表 [5,6,7]修改为元组(5,6,7),然后我们再分别使用+和+=试试:
1234567891011121314151617# 使用+操作a = [1,2 ,3]c = a + (5,6,7)print(a)# 输出结果:TypeError: can only concatenate list (not "tuple") to list# 使用+=操作a = [1,2 ,3]a += (5,6,7)print(a)# 输出结果:[1, 2, 3, 5, 6, 7]
所以看到没,我们这个+=可以连接不同类型的数据类型,知道为什么么,因为它里面包含了一个魔法 ...
Python高级编程(20):python中序列类型的abc继承关系
1from Lib import _collections_abc
我们所有关于序列类型的模块都在abc这个里面,前面也说过python是基于协议开发的语言,我们现在又要谈到我们的鸭子模型了。只要具有相应的魔法函数,它就具有了相应的功能:
如果我们要定制一个不可变的容器,如String,那么代码中就不能有修改容器数据的方法,如__setitem__(), __delitem__();
如果希望定制的容器支持reversed()这个内置函数,那么容器中需定义__reversed__()方法,从而提供对内置函数reversed()的支持;
在容器中,查询容器”容量”的方法是通过len()这个内置函数来实现,所以容器中需要定义__len__()方法;
如果希望容器支持读,写和删除功能,那么就要实现对应的方法:__getitem__(), __setitem__(), __delitem__();
Python高级编程(19):python中的序列分类
python中的序列其实就是一种协议,Python是基于协议而开发的。我们依据两个维度来将序列进行分类,一个是按照是否必须存储同一类型分为容器序列和扁平序列;另一个则是序列是否可变,分为:可变序列和不可变序列。
容器序列:list、tuple、deque;扁平序列:str、bytes、bytearray、array.array。
容器序列就是可以存储不同类型数据结构的对象,只是一个容器而已:
12345678a_list = []a_list.append(123)a_list.append("nihao")print(a_list)# 输出结果:[123, 'nihao']
而扁平序列就是只能存储同一数据类型的对象。
可变序列:list, deque,bytearray、array
不可变序列:str、tuple、bytes可变序列就是允许你往里面添加数据,不可变序列就是不允许你修改里面的内容。
Python高级编程(18):contextlib简化上下文管理器
本来我们这个应该是和前面的with语句放在一块的,但是我想多写一篇,目的就是为了突出使用contextlib这个模块以后,我们的上下文管理器简化了很多。
我们还是先来看一段代码:
1234567891011121314151617import contextlib@contextlib.contextmanagerdef file_open(file_name): print("file open") # 此处代码就相当于之前的enter魔法函数实现的代码 yield {} # 必须是yield一个生成器,可以没有{},但是yield关键词必须有 print("file end") # 此处代码就相当于之前的exit魔法函数实现的代码with file_open("envse.txt")as file_read: print("file is reading")# 输出结果:file openfile is readingfile en ...
Python高级编程(17):python中的with语句
要使用 with 语句,首先要明白上下文管理器这一概念。有了上下文管理器,with 语句才能工作。
上下文管理协议(Context Management Protocol):包含方法 __enter__() 和__exit__(),支持该协议的对象要实现这两个方法。
上下文管理器(Context Manager):支持上下文管理协议的对象,这种对象实现了__enter__() 和__exit__()方法。上下文管理器定义执行 with 语句时要建立的运行时上下文,负责执行 with 语句块上下文中的进入与退出操作。通常使用 with 语句调用上下文管理器,也可以通过直接调用其方法来使用。说白了就是你只要是包含了__enter__() 和__exit__()这两个魔法函数,我就可以把你当做一个上下文管理器(鸭子类型)来操作。
我们先来看一段代码,给这个函数实现上下文管理协议:
12345678910111213141516171819class Sample: def __enter__(self): # 获取资源 print("enter&q ...
Python高级编程(16):mixin继承
mixin混合模式的特点:1、mixin类功能单一;2、不和基类关联,可以和任意基类进行组合,基类可以不和mixin关联就能初始化成功;3、在mixin中,不要使用super这种用法;最后尽量以mixin结尾
参考文章:Python mixin模式
Python中的Mixin模式
Python高级编程(15):super真的是调用父类吗?
这一部分非常重要,我相信很多人心中一直觉得super函数就是调用父类,但是结果是这样吗,我们来好好聊一下这个super。我们先来看一段代码:
1234567891011121314class A: def __init__(self): print("A")class B(A): def __init__(self): print("B")if __name__ == '__main__': b = B()# 输出结果:B
这个是没有问题的,很好理解,我们接着来看下一段代码:
12345678910111213class A: def __init__(self): print("A")class B(A): def __init__(self): print("B") super().__init__()# 输出结果:BA
有人说这不就是调用了父类的方法么,我暂且不说话。并向你扔了2个问 ...