python - 官方简易文档篇(2)数据结构

本文深入探讨Python中的数据结构,特别是列表的各种特性,如切片、插入、扩展、删除等操作。此外,还介绍了元组、集合、字典等其他序列和数据类型,以及它们在存储和操作数据时的特性和用途。文中还讨论了列表作为栈和队列的使用,以及列表推导式的应用。
摘要由CSDN通过智能技术生成

数据结构

列表的更多特性

切片的异类用法,在列表中插入另外的列表片段

下面的演示中会多次用到切片,并且使用list1[len(list1):],这个式子中,意指从索引位置开始,直到最后。但索引位置是正好是最后一位的下一位,而我尝试使用更大的数字,仍能成立,所以在切片中的切片数可以是任意正数、0、负数的!
但这个切片负值又给我们带来了新的世界:

a=[1,2,3]
a[2:2] # [] a[2:1] a[2:0] ...
a[2:2]="abc" # [1,2,"a","b","c",3]

其实以上是我从[-666:-1]改进过来的,相当于[len(list)-1:len(list)-(>=1)]

因为在切片和索引中,负数是和正数有对应关系的,所以这里就不论了。

以上,当索引1>索引2时,切片是空,但对这个切片赋值时,等同于在那个位置插入一段列表,这里列表不是以元素存在,而是以一个列表片段存在。貌似列表的方法中还真没有这个功能,所以如果官方并没有改变规则的话,大家可以尝试以下这个方法,反之,还是乖乖的使用list1=list1[:a]+list2+list1[a:]

总结:

在头部插入列表片段,非插入元素。
list1[:0]
list1[0:0] 

在索引位置i插入
list1[i:i]
list1[i:<i]

在末尾插入
list1.extend(list2)
list1[len(list1):]
list1[len(list1):len(list1)] 
list1[>len(list1):]

以上均有共同特点,其切片内容为[],插入位置就是索引1的位置

list.append(x)

在列表的末尾添加一个元素。
相当于a[len(a):]=[x]

995 ns vs 4.22 µs

%%timeit
a=[]
for i in range(10):
    a.append("1")
#
995 ns ± 22.4 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
a=[0,1,2,3]
x=4
a[len(a):]=[x]

a # [0, 1, 2, 3, 4]

a[i:]=[i] 节省4µs
但本质上i还是有区别的!
毕竟list.append(x)就是专门为了增加元素而设计的。属于大师级的机器语言。
而a[len(a):]=[x],无奈使用切片的写法,因为使用索引的方法,他超界了,而且使用切片,又只能使用list赋值,而不能使用最单纯的元素赋值。

在第一篇的文档笔记中曾经使用a=a[:]+[x]的比较,则是更加远离列表追加元素的概念。运算时间也是更加的长!

list.extend(iterable)

iterable包括str

使用可迭代对象中的所有元素来扩展列表。
相当于a[len(a):]=iterable
1.8 µs vs 4.43 µs
以上两个写法中,iterable可以包括str,看来定义中是以iterable形式存在的时候,字符串会被当做一个iterable的字符序列处理,而不是一个字符串!

a[len(a):]="abc"
a # [0, 1, 2, 3, 4, 'a', 'b', 'c']
a.extend("abc")
a # [0, 1, 2, 3, 4, 'a', 'b', 'c', 'a', 'b', 'c']

list.insert(i,x)

在给定的位置插入一个元素。第一个参数是要插入的元素的索引,所以a.insert(0,x)插入列表头部,a.insert(len(a),x)等同于a.append(x)。这里索引>len(a)同样效果!

最开始说的切片插入的异类用法,插入的是iterable,这个插入的就是一个元素。

list.remove(x)

移除列表中第一个值为x的元素。如果没有这样的元素,则抛出ValueError异常!

list.pop([i])

删除列表中给定位置的元素并返回它。如果没有给定位置,a.pop()将会删除并返回列表中的最后一个元素。
(方法签名中i两边的方括号表示这个参数是可选的,而不是要你输入方括号。你会在Python参考库中经常看到这种表示方法)

list.clear()

del a[:]

移除列表中的所有元素。等价于“del a[:]”

list.index(x[,start[,end]])

返回列表中第一个值为x的元素的从零开始的索引。如果没有这样的元素,将会抛出ValueError异常。
可选参数start和end是切片符号,用于将搜索限制为列表的特定子序列。返回的索引是相对于整个序列的开始计算的,而不是start参数。

list.count(x)

返回元素x在列表中出现的次数

list.sort(key=None,reverse=False)

原地操作

对列表中的元素进行排序(参数可用于自定义排序,解释请参见sorted())
昨天看的函数最后讲的是lambda,key=lambda x:abs(10-x),等这类操作,他返回的是一个类列表,与原列表一一对应,对这个生成的类列表排序,就是对原列表的对应规则排序!

def f(i):
    return abs(5-i),-i
a=range(10)
a.sort(key=f)
#
[5, 6, 3, 2, 1, 56, 321]

昨天没能写出,对应lambda的函数,这次参考网友的文章,写出来了!
用list.sort(key)排序

def f(i):
    return abs(5-i),-i
a=list(range(10))
a.sort(key=f)
#
[5, 6, 4, 7, 3, 8, 2, 9, 1, 0]

abs(5-6) ==abs(5-4) 于是设置了第二个排序规则,-i,这样就是-6,-4,默认升序排列,小的那个在前面
多列排序

list.reverse()

翻转列表中的元素

list.copy()

返回列表的一个浅拷贝,等价于a[:]

a=[1,2,3]
b=a 贴牌
b=a.copy() 浅拷贝 一层复制,如果元素中包含列表等可变元素,这个元素仍是贴牌

import copy
b=copy.deepcopy(a) 深复制,每一层都生成全新的数据,a变,b不再变

列表作为栈使用

列表的方法是的列表作为堆栈非常容易,最后一个插入,最先取出(“后进先出”)。
要添加一个元素到对战的顶端,使用append()。
要从堆栈顶部取出一个元素,使用pop(),不用指定索引。

列表作为队列使用 deque与list的不同之数据指针存储

列表也可以用作队列,其中先添加的元素被最先取出(“先进先出”)。
然而列表用作这个目的相当低效。因为在列表的末尾添加和弹出元素非常快,但是在列表的开通插入或弹出元素却很慢(因为所有的其他元素都必须移动一位)
若要实现一个队列,可使用collections.deque,它被设计成可以快速地从两端添加或弹出元素。例如:

from collections import deque
queue = deque(["a","b","c"])
queue.appendleft("d") # deque(["d","a","b","c"])
queue.popleft() # "d" # deque(["a","b","c"])
queue.extendleft([1,2,3]) # deque([3,2,1,"a","b","c"])
queue.pop(3) # ERROR
help(deque.rotate)
扭来扭曲意义呢?
不输入或输入奇数,就是反转序列,输入偶数,没变化

工具:ipython、hxd
目标:deque、list
命令:.__sizeof__(),len(),id()等等
关键:数据指针区在本体的第四个字段(0x18~0x20),即hxd的第二行后半段,跳转后,既是数据指针区

结果:
deque:主体大,608字节(参数多),数据指针区相对固定(不可排序,仅支持逆序)
list:主体小,112字节(参数少),数据指针区对应list内容的变化(对于先进先出效率低)

先进先出:
deque:[0 1 2 3 4 5] —出栈底—> 0[1 2 3 4 5] 实质是仅在deque的主体中
list:0 1 2 3 4 5 —出栈底—> 1 2 3 4 5<< 每个指针都要往前移动,相当于a[:]=a[1:]的操作,列表要完全复制一次,所以当列表越长时,出栈底的效率越低

逆序:
deque:[0 1 2 3 4 5] reverse:False —reverse—> [0 1 2 3 4 5] reverse:True 这里无论是reverse还是rotate,只要显示结果和存储结果相逆序,就会在主体的逆序标记上打勾勾
list:0 1 2 3 4 5 —reverse—> 5 4 3 2 1 0 这个真的又要再来一遍 a[:]=a[::-1]

其他:
deque:insert,del a[i]仍然可以在序列内部插入删除参数
但是pop(i)不再能使用,只能使用pop()
sort不能使用,但多了个rotate
核心:增加了appendleft、extendleft、popleft三种两端操作的用法
extendleft的时候,被插入的序列是逆序的,extend还是常规顺序的

而类似sort这种会打乱内容顺序而非前后顺序逆序的操作,deque是不存在的,因为他的存在都是围绕着数据指针区固定不变而设计的!

%%timeit
a=list(range(100))
for i in range(30):a.pop(0)
7.55 µs 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值