更多课程 选择中心


Python培训

400-111-8989

Python内置数据结构大总结

  • 发布:#
  • 来源:小白的技术客栈
  • 时间:2017-08-31 16:38

内置据结构大总结 今天不讲解新的内容,主要回顾一下以往讲过的内置数据结构,来个大总结。

五种线性结构

列表

元组

字符串

bytes

bytearray

两种非线性结构

字典

集合

列表、元组、字符串属于线性结构,我们可以对其进行切片操作、解包/封包操作。

序列类型操作符

下表是所有序列类型都适用的操作符:

序列操作符作用

seq[ind]获得下标为ind的元素

seq[ind1:ind2]获得下标从ind1到ind2间的元素集合

seq * expr序列重复expr次

seq1 + seq2连接序列seq1和seq2

obj in seq判断obj元素是否包含在seq中

obj not in判断obj元素是否不包含在seq中

几种数据结构的共性

这几种数据结构的共性:

都是顺序存储

顺序访问

可迭代对象(可迭代对象可以用len方法获取其长度)

通过索引进行元素的访问

可以进行切片操作

切片

切片不会对原有的序列做任何修改,切片的语法为:

seq[start:stop]

从索引start开始,到索引stop结束,不包含stop,返回新的序列,不会对原有的对象做任何修改。

几个特性:

start超出索引范围:start = 0

stop超出索引范围:stop = -1

负数索引:实际上可转化为:len(seq) + index

当start >= stop时,返回空列表

slice的实现:

lst = list(range(0, 10))def slice(lst, start=0, stop=0): if start < 0: start = len(lst) + start if stop <= 0: stop = len(lst) + stop if stop <= start: return [] if stop > len(lst): stop = len(lst) if start < 0: start = 0 ret = [] for i, v in enumerate(lst): if i >= start and i < stop: ret.append(v) return retprint(slice(lst, 3, 2))print(slice(lst, 2, 5))print(slice(lst, -100, 100))

运行结果为:

: [] : [2, 3, 4] : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

如果有了步长之后,上面的规则就会发生变化。接下来加入步长的slice实现:

def slice(lst, start=0, stop=0, step=1): ret = [] if stop < 0: tmp = start start = tmp stop = start current = start while current < stop: try: ret.append(lst[current]) except IndexError: pass current += step return ret

切片的一些常用操作:

>>> lst = list(range(0, 10))>>> lst[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]>>> lst[:] # 等效于copy方法>>> lst[-5:-3] # 支持负数索引# start大于等于stop时,返回空列表>>> lst[3:1]# 列出偶数,步长为2lst[::2][0, 2, 4, 6, 8]# 列出偶数,步长为2,并倒序输出lst[::2][::-1][8, 6, 4, 2, 0]# 列出奇数,步长为2,并倒序输出lst[::-2][9, 7, 5, 3, 1]# 列出偶数,步长为2,并倒序输出lst[-2::-2][8, 6, 4, 2, 0]

索引

如果索引超出范围,将引发IndexError的异常。修改元素的时候,如果超出索引范围,也同样引发IndexError异常。

index(value)方法根据value找索引

count(value)方法统计value出现的次数

enumerate的实现:

def enumerate(iterator): i = 0 for v in iterator: yield i, v i += 1def enumerate(iterator): ret = [] i = 0 for v in iterator: ret.append((i, v)) i += 1 return ret

引用

列表批量赋值:

## 当赋值的序列连续时# 对切片赋值,会替代原来的元素>>> lst = list(range(0, 10))>>> lst[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]>>> lst[3:5] = ['x', 'y', 'z']>>> lst[0, 1, 2, 'x', 'y', 'z', 5, 6, 7, 8, 9]>>> lst = list(range(0, 10))>>> lst[3:5] = ['x']>>> lst[0, 1, 2, 'x', 5, 6, 7, 8, 9]>>> lst = list(range(0, 10))>>> lst[3:5] = 'x'>>> lst[0, 1, 2, 'x', 5, 6, 7, 8, 9]## 当赋值的序列不连续时>>> lst = list(range(0, 10))>>> lst[3:8:2] = ['x', 'y', 'z']>>> lst[0, 1, 2, 'x', 4, 'y', 6, 'z', 8, 9]>>> lst = list(range(0, 10))>>> lst[3:8:2] = ['x']ValueError: attempt to assign sequence of size 1 to extended slice of size 3>>> lst[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

不建议使用以上的方式对切片赋值的操作。

解包/封包

解构与封装可以叫做解包与封包。

解构把集合里的元素复制给变量;

封装是用变量构建元组。

解构:按照元素顺序,把线性解构的元素依次赋值给变量。

封装的例子:

t = 1, 2print(t)(1, 2)print(type(t))<class 'tuple'>

定义一个元组,可以省略小括号。

t1 = (1, 2)t2 = 1, 2print(t1 == t2) # t1与t2是等效的True

封装出来的是元组。封装没有什么难度。解构的变化多样,接下来重点看看解构。

先看一个例子:

In[29]: def swap(a, b): ...: i = a ...: a = b ...: b = i ...: return (a, b) ...: In[30]: swap(1, 3)Out[30]: (3, 1)

对上面的代码进行改写,由3行代码,变成了一行代码:

In[31]: def swap(a, b): ...: a, b = b, a ...: return (a, b) ...: In[32]: swap(1, 3)Out[32]: (3, 1)

对于如下的代码操作,就是解包:

In[33]: x, y = (1, 3)In[34]: xOut[34]: 1In[35]: yOut[35]: 3

上面的代码使用的是元组,列表也是可以的:

In[36]: a, b = 1, 3In[37]: aOut[37]: 1In[38]: bOut[38]: 3

接下来看一下封包:

In[39]: t = 1, 3In[40]: tOut[40]: (1, 3)In[41]: type(t)Out[41]: tuple

继续看例子:

In[42]: head, tail = list(range(0, 10))# 将会得到如下的错误,因为=两边的元素数量不一致导致的ValueError: too many values to unpack (expected 2)In[43]: head, *tail = list(range(0, 10))In[44]: headOut[44]: 0In[45]: tailOut[45]: [1, 2, 3, 4, 5, 6, 7, 8, 9]In[46]: *head, tail = list(range(0, 10))In[47]: headOut[47]: [0, 1, 2, 3, 4, 5, 6, 7, 8]In[48]: tailOut[48]: 9

如果对一个含有2个元素的列表进行解包:

In[49]: head, *tail = [1, 2]In[50]: headOut[50]: 1In[51]: tailOut[51]: [2]

如果对一个含有一个元素的列表进行解包:

In[52]: head, *tail = [1]In[53]: headOut[53]: 1In[54]: tailOut[54]: []

如果对一个空列表进行解包:

In[55]: head, *tail = []ValueError: not enough values to unpack (expected at least 1, got 0)

针对上述例子的总结:

左边不能只有一个星号,还要有其他元素

如果左边不用星号,那么左边的元素个数要与右边的元素个数相同

左边变量数小于右边元素个数,且左边没有加星号会报错

元素按照顺序赋值给变量

变量和元素必须匹配

加星号变量,可以接收任意个数的元素

加星号的变量不能单独出现

针对上述,写一个具体的例子:

def it(lst): if lst: head, *tail = lst print(head) it(tail)it(list(range(0, 10)))0123456789

更复杂一点的例子:

In[63]: head, *tail = [1, 2, 3]In[64]: headOut[64]: 1In[65]: tailOut[65]: [2, 3]

下面这个例子,在Python2中不能实现:

In[59]: head, *mid, tail = [1, 2, 3, 4, 5]In[60]: headOut[60]: 1In[61]: midOut[61]: [2, 3, 4]In[62]: tailOut[62]: 5

接下来还有更好远的,如果我们要丢弃=右边某个值,可以使用下划线来,演示如下:

In[66]: lst = list(range(0, 10))In[67]: lstOut[67]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]In[68]: a, b, _, c, *_ = lstIn[69]: aOut[69]: 0In[70]: bOut[70]: 1In[71]: cOut[71]: 3

如果我们只想要序列的首位两个元素,可以这样操作:

In[72]: head, *_, tail = lstIn[73]: headOut[73]: 0In[74]: tailOut[74]: 9

再来一发,两边结构要一样:

In[75]: lst = [1, [2, 3], 4]In[76]: a, (b, c), d = lstIn[77]: aOut[77]: 1In[78]: bOut[78]: 2In[79]: cOut[79]: 3In[80]: dOut[80]: 4

对上面的例子,再来稍微变化一下,不过两边的结构要一样,解构是支持多层次的。:

In[81]: lst = [1, [2, 3, 4, 5, 6, 8], 9]In[82]: lstOut[82]: [1, [2, 3, 4, 5, 6, 8], 9]In[83]: a, (b, *_, c), d = lstIn[84]: aOut[84]: 1In[85]: bOut[85]: 2In[86]: cOut[86]: 8In[87]: dOut[87]: 9

注意:

解包的时候,两边的结构要一致 (重要的事情说三遍)

解包的时候,两边的结构要一致 (重要的事情说三遍)

解包的时候,两边的结构要一致 (重要的事情说三遍)

只要两边结构一样就行

>>> a, (b, (c, (d,))) = [1, [2, [3, [4]]]]>>> a1>>> b2>>> c3>>> d4

python的一个惯例,使用单个下划线表示丢弃该变量。单个下划线也是Python合法的标识符,但是如果不是要丢弃一个变量,通常不要用单个下划线表示一个有意义的变量。

head, *_ = 'I love python'print(head)Ikey, *_, value = 'env = properties'.partition('=')print(key)envprint(value)properties

非常复杂的数据结构,多层嵌套的线性结构的时候,可以用解构快速提取其中的值。

预约申请免费试听课

填写下面表单即可预约申请免费试听! 怕学不会?助教全程陪读,随时解惑!担心就业?一地学习,可全国推荐就业!

上一篇:如何通过Python 对网站的漏洞进行检查
下一篇:不可错过的Python技术博客(网站)

2021年Python全套免费视频教程在哪里?

Python编程学习路线

Python最高有几级?

人工智能与语音遥控的区别?

  • 扫码领取资料

    回复关键字:视频资料

    免费领取 达内课程视频学习资料

Copyright © 2023 Tedu.cn All Rights Reserved 京ICP备08000853号-56 京公网安备 11010802029508号 达内时代科技集团有限公司 版权所有

选择城市和中心
黑龙江省

吉林省

河北省

湖南省

贵州省

云南省

广西省

海南省