您的位置:首页 > 理论基础 > 数据结构算法

python程序设计第3课第二章复合数据结构

2020-05-11 04:13 525 查看

第二章 复合数据结构

列表(list):方括号

元组(tuple):圆括号

字典(dict):大括号,键(key)值(value)对的集合,键值对间用逗号分隔,键后有冒号

集合(set):大括号,元素不能重复

字符串(str) 这讲暂时不讲

一,双向索引的概念

除dict和set之外,list,tuple和string都支持双向索引
*前两种没有顺序之说自然也就没有索引的概念了

所谓双向所以就是通过下标索引访问元素有两种顺序。一种从左开始且起始下标为0,一种从右开始且起始下标为-1

二,可变与不可变(mutable immutable)。

python中的可变类型:list,set,dict
python中的不可变类型:string,tuple

如list可以下标索引的方式改变元素,tuple则只能访问而不可改变,但是实际情况可以更微妙

例:
>>>a=([4,],[1,2,3],[4,5,6])
>>>a[0]
[4]
>>>type(a[0])
<class'list'>
>>>a[0]=[1,2,3]  报错

>>>a[0][0]=2     不报错

三,列表

左右方括号,逗号分隔,列表里面可以放不同类型的东西,还可以嵌套列表

例:[‘spam’, 2.0, 5, [10, 20]] [[‘file1’, 200, 7], [‘file2’, 160, 9], False, None]

1.列表操作
  • .append(elem)
  • .extend(list)
  • .insert(index,x)
  • .remove(elem)
  • .pop()
  • .index(elem)
  • .count(elem)
  • .copy()
  • .remove(elem)
  • .reverse()
  • .sort()

具体的细节自己看PPT。注意list.append(elem)和list.extend(list)的区别,前者接受元素,
后者接受列表

2.列表对象的创建

法一:直接等于号赋值给变量

法二:利用bulit-in function中的list()构建列表,只接受一个可迭代对象,把可迭代对象(如元组
,字符串,range对象)转化为list

例:>>> my_list = list((3, 5, 7, 9, 11))    输入一个元组,加上圆括号,否则报错
>>> my_list
[3, 5, 7, 9, 11]

>>>mylist=list[]                        创建空列表
Built-in Function:range()

range([start,]stop[,step]):生成一个整数序列,第一个参数默认0,第三个参数步长默认1
注:方括号表示该参数可有可无

在python2里有xrange(),和range差不多,只是xrange()返回的是一个可迭代对象。range()则返回一个列表,这在python3里没有,python3的range()直接返回可迭代对象,要用list(range(5))才能转化为一个列表使用

例:>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> xrange(10)
xrange(10)
>>> list(xrange(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

range的用法示例:

for i in range(4):
...  print i
...
0
1
2
3.列表的删除

把下标为2的值删去>>>del a[2] 把a完全删去>>>del a

*del是个命令,不是函数

*直接b=a,删去a元素时b也会跟着改变。但是完全删去a,b则不会消失

例:  >>>a=[1,2,3]
>>>b=a
>>>del a[1]
>>>b
[1,3]
>>>del a
>>>b
[1,3]
4.列表元素增加
法一:

直接>>>b=a+[4]

*一定要加方括号,不然会认为你是要列表加整数而报错
*这种方法创建的是新列表,id会改变,所以不推荐

法二:

.append(elem)方法: >>>a.append(4)不会改变id,直接在原地修改列表

*>>>b=a.append(5)是错误用法,这个函数没返回值(None)
*import time 这个package中的time.time()可以用来计时
*再次赋值,变量所指向的对象的内存地址会发生变化,但是如果通过下标修改值(如修改a[1])。整个列表的id是不变的,不过id(a[1]) 则会变化。因为列表里含这些元素不是含这些元素本身,而是含对这些元素的引用。由于同样的原理对一个列表用.remove(elem) .append(elem)等方法不会改变a的id

法三:

.extend(list)方法:注意与append(elem)的区别,把另一个迭代对象的各元素添加至尾部,
不改变id

例:
>>>a=[1,2,3]
>>>a.append([4,5])
>>>a
[1,2,3,[4,5]]
>>>a.extend("str")
>>>a
[1,2,3,[4,5],'s','t','r']
法四:

.insert(i,x)方法,在索引为i的元素后加上x

法五:

‘’*’'号运算

*这种方法会产生新列表。不过并不是在内存里生成多个对象的拷贝,实际上是对已生成对象的复用,所以改变其中一个值时相应的引用也会被修改。

5.列表元素的删除
法一:

del list[index]

法二:

.pop(): >>>a.pop() 删除最后一个元素并返回其值 >>>a.pop(2)删除索引2并返回其值

*超出索引范围会报错

法三:

.remove(elem):>>>a.remove(7)没有返回值,删除列表中的第一个出现的7

*找不到元素会报错

关于元素删除的另一个问题:如何删除列表中的指定元素?

*注意循环+remove(elem):这种方法很容易出错,比如遇到连续待删除元素,因为在循环过程中一
直在原地修改列表

例子:my_list = [1, 2, 1, 2, 1, 1, 1]
for idx,val in enumerate(my_list):
if val == 1:
my_list.remove(val)
print my_list
*enumerate接受一个可迭代对象,返回可迭代对象的每一个值,同时返回每一个元素对应的下标索引,实际返回一个tuple

*可以看到每次循环时删去一个1都会导致产生一个新的列表,idx和val的值会产生不匹配的现象,具体可以看老师的录像里的跟踪执行,过程中idx一直在自动增加,会导致你的一些元素被跳过,最终的结果是[2,2,1]

正确的删除指定元素方法是[val for val in my my_list if val!=1]
先 for val in my_list循环遍历列表,if val!=1就把它拿出来执行完毕时组合形成一个新的列表,
原列表不变

7.切片返回shallow copy

复制形成一个新的列表,在内存中开辟新的对象 >>>b=a[:]。此时>>>a is b 就是false

8.shallow copy与deep copy的区别

shallow copy与deep copy的区别:对于复杂对象不同。比如列表的列表,shallow copy只限于顶层复制,对于第二层的列表不会在内存中重新分配空间创造新的对象。具体的例子见课件

*deep copy使用时要import copy,然后注意copy.copy() (shallow)与copy.deepcopy()(deep)不同

9.切片操作

切片操作对list,tuple,range对象,string等类型都适用

两个冒号且第一个为开始索引,默认0,第二个为结束索引,默认为对象长度,第三个为步长,默认为1,不会有超出异常。具体应用见PPT

切片操作的两个应用(具体见PPT,没仔细讲):
1.使用切片原地修改列表
2.使用del和切片操作结合删除元素

10.列表元素访问

具体见PPT,没仔细讲

.index(elem)

11.列表元素计数

具体见PPT,没仔细讲

.counts(elem)

12.列表成员资格判断

具体见PPT,没仔细讲

用in关键字

13.列表排序

.sort():>>>b=a.sort() sort原地升序排列a,没有返回值,这里b为none,得不到排序后的列表

sorted(list):>>>sorted(a) 产生一个新的排序后列表,最早的列表不变。注意这是内置函数,不要写成a.sorted(a)

*注意对象方法和内置函数的区别,方法本质上就是函数,使用时用对象本身.对象方法(如a.sort()就是调用列表对象a的对象方法,sort作为对象方法,调用时必须依赖于一个列表对象)的格式,这和使用内置函数的格式不同,如sorted()不依赖于任何列表对象,相反它接受一个列表对象作为参数

.reversed():原地逆序排列

reversed(list):返回一个逆序排列的可迭代对象,原列表不变
*迭代对象只是一次性的,例子里list遍历后里面就没值了,再尝试用for i in b打印时就没有输出
值了

14.用于序列操作的常用内置函数(具体见PPT)

max,min(list):还可用于tuple,range

sum(list) :还可用于tuple,range

len(list) :还可用于string,dict,tuple

*Built-in Function:zip(list1,list2,…)

将多个列表对应位置元素组合为元组,并返回包含这些元组的列表

*zip函数在python3中返回一个可迭代对象,这与python2不同
*python3引入可迭代对象对语法没什么很大的影响,在for循环里可以直接遍历可迭代对象,不用转换

15.列表推导式

(这里讲的比较简略并在第4课中又稍微讲了一下,但都没有细讲)

例:>>>a=[x*x for x in range(10)]
*x只是个变量,随便叫什么都可以

列表推导式的复杂用法 1.嵌套列表平铺
例:
>>>vec=[[1,2,3],[4,5,6],[7,8,9]]
>>> [num for elem in vec for num in elem]
2.列出当前文件夹下所有python源文件
例:
>>> [filename for filename in os.listdir('.') if filename.endswith('.py')]
*在里面用if-else把for里面的元素filename取出来,对filename进行判断
3.过滤不符合条件元素
例:
>>>[val for val in list1 if val>0]
4.多个循环,多序列元素任意组合同时配合条件语句过滤特定元素
例:
>>> [(x, y) for x in [1, 2, 3] for y in [3, 1, 4] if x != y]
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
5.在列表推导式中使用外部函数 6.列表推导式支持文件迭代

*被循环的东西只要是个可迭代对象就行,open打开一个文件并把文件逐行作为可迭代对象返回出来

例:
>>>fp=open('test.py','r')
>>>print [line for line in fp]
['aa\n','bbb\n','ccc\n','ddddd\n']
>>>fp.close()
*Built-in Function:enumerate (sequence,start=0)

返回一个枚举对象。序列(sequence)必须是序列,迭代器或其他支持迭代的对象。以一个个元组的形式返回(index,value),并组合成一个enumerate(枚举)对象,可以转换为列表

编辑于 2020-2-28 18:52
修改于 2020-4-25 23:01

CS_Lee_ 原创文章 16获赞 0访问量 2305 关注 私信
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: