Python中的列表和元组

1.列表List

问题:现在要保存100个人的姓名,如何操作?
答案是将这100个人的姓名存放在列表中。

列表是一种可变的序列类型,能够存储多个元素

列表的特点:

  • 列表中元素可以是多种数据类型。
  • 列表中的元素的有序的,因此用类似于数组下标的方式进行索引访问。
  • 列表是可变类型,列表内的元素可以修改。

1.1 创建列表

列表创建主要有两种方式:

  • 直接使用一对[]即可,里面内部可以放上需要放入的元素。
  • 通过list()函数来构造列表,函数无参数时创建空列表,有参数时,例如传入一个元组,可以将该元组转换成列表。

定义列表非常简单,使用一对[]即可。例如定义一个空的列表:

elist = []

当然也可以定义非空的列表,元素之间使用逗号,分隔

lis = [1, 2, 3, 4]

Python中,列表中的元素类型可以是不同的:

lis = [1, 2.3, 5 + 8j, “apple”]

通过list()函数构造列表:

a = (1,2,3)
b = list(a)
print(b)

# output
# [1, 2, 3]

1.2 列表运算符

列表(序列)也是支持部分运算,因为列表可以包含多个元素,相比之前学习的数值类型(仅包含单个值)来说,其计算规则相对复杂一些。

列表支持如下的运算:

符号说明
x + y返回连接,合并x与y两个列表后的新列表,x,y本身不变
x * n返回将序列重复n次(所有元素重复n次)。
e in x如果e在x中,返回True,否则返回False。
e not in x如果e不在x中,返回True,否则返回False。
x 比较 y依次比较x,y的元素(>,>=,<,<=,==,!=)。
x is,is not y判断x,y是否为同一个列表。
x 布尔 y与数值类型的布尔运算(and或or)规则相同(返回两个列表中的一个)

说明

假设上表中,x与y是列表类型,e为列表中的元素,n为整数。

1.3 列表索引

定义列表后可以通过索引来访问列表的元素。访问方式为:

列表名[索引值]

索引是从0开始编号的最大索引值为列表的长度- 1,列表(序列)的长度可以通过len()函数获得。

同时,列表的索引也支持负值,表示倒数第n个位置。例如:list[-1]表示倒数第一个(最后一个)元素。列表的有效索引值区间为[-length, length - 1](length为列表的长度)。如果索引不在有效区间,将会产生错误。

列表是可变的序列类型,我们除了可以通过索引获取元素的值,也可以改变元素的值。

1.4 列表切片

切片可以用来操作列表(序列)一个区间的元素。切片的语法为:

列表名[start : end : step]

startendstep都是可选的,也都可以是负值。

注意切片截取元素的方向。两个端点同时存在,与两个端点缺失一个(或全部缺失),表现的不同。通过切片也可以修改列表的一个区间。

1.5 列表相关方法

  • append(obj):在原列表尾部添加一个元素。

  • insert(index, obj):在列表索引位置index处插入一个元素。

  • remove(value):删除列表中第一个value元素。

  • pop([index]):将index处的元素从列表中移除并返回,不写则默认最后一个元素。

  • index(value, [start, stop]):返回value的索引位置。

  • count(value):返回列表中value的个数。

  • reverse():逆序列表。

  • extend(iterable):可以一次添加多个元素。注意添加字符串等可迭代对象时会拆开来添加。

  • clear():清空列表。

  • copy():复制列表,浅拷贝。

  • sort(key=None, reverse=False):给列表排序。

  • del():除了可以删除变量名,也可以用来删除列表的元素。例如:del lidel li[0],del[0:3]

1.6 列表的复制

列表的内存存储

  • id(value)函数:返回value的地址。
  • 浅拷贝:列表的copy方法。copy模块的copy()方法,只拷贝父对象,不会拷贝对象的内部的子对象
  • 深拷贝:copy模块的deepcopy()方法,拷贝对象及其子对象

示例:

import copy
a = [1, 2, 3, 4, ['a', 'b']]  #原始对象
 
b = a  #赋值,传对象的引用
c = copy.copy(a)  #对象拷贝,浅拷贝
d = copy.deepcopy(a)  #对象拷贝,深拷贝
 
a.append(5)  #修改对象a
a[4].append('c')  #修改对象a中的['a', 'b']数组对象
 
print ('a = ', a)
print ('b = ', b)
print ('c = ', c)
print ('d = ', d)
 
# output
'''
a =  [1, 2, 3, 4, ['a', 'b', 'c'], 5]
b =  [1, 2, 3, 4, ['a', 'b', 'c'], 5]
c =  [1, 2, 3, 4, ['a', 'b', 'c']]
d =  [1, 2, 3, 4, ['a', 'b']]
'''

1.7 列表推导式

列表推导式是一种创建列表的简洁方式

当我们需要创建一个列表,该列表中的每个元素是通过另外一个列表(或可迭代对象)中的每个元素(或部分元素)经过运算获得时(即当需要创建的列表元素依赖于另外一个可迭代对象的元素时),就可以考虑使用列表推导式来实现。

列表推导式的语法为:

[表达式 for 更多的forif]

如,将l1中的每个元素乘以2然后保存在l2中:

l1=[1,2,3,4]
l2=[x*2 for x in l1]

如,将l1中的每个大于2的元素乘以2然后保存在l2中:

l1=[1,2,3,4]
l2=[x*2 for x in l1 if x>2]

列表推导式中的变量

for循环中的变量会在for循环后继续有效(这可能不是我们期望的),而列表推导式中声明的变量仅在列表推导式中有效(如果赋值,与左侧变量也不会冲突)。

1.8 列表的遍历

列表具有索引,可以使用while循环遍历。序列类型都是可迭代对象,因此,序列可以使用在for循环中进行遍历。

列表是可以嵌套的,即列表中的元素依然是列表类型。例如,如果保存一个班级的所有学生的名字,是一个一级列表,可以要保存每个学生所选修的课程,就是一个二级列表了。

2.元组

2.1 定义与基本操作

元组是一种不可变的序列。即元组一经创建,就无法再进行修改,试图对元组进行的任何修改均会产生错误。除了不可变性,元组与列表非常相似,可以近似的认为,元组是一种不可变的列表类型。

创建元组:

元组使用()表示,多个元素使用逗号,分隔。但是当元组仅有一个元素时,必须在元素后面加上逗号,,否则不是元组类型。(重要的是逗号,不是小括号)

以下情况下,元组需要使用()

  • 长度为0的元素(空元组)
  • 元组嵌套
  • 元组作为表达式的一部分

然而,为了令程序更加具有可读性,建议当使用元组时,总是使用()

元组的操作:

  • 索引
  • 切片
  • 运算
  • 遍历

2.2 相关方法

因为元组是不可变的序列,因此所有修改序列的方法都不适合元组。

  • count(value)
  • index(value, [start, [stop]])

2.3 元组的意义

元组作为一种不可变序列,可以保证数据在程序运行过程中不会意外由自己或其他人修改(例如在函数参数传递中),这样可以保证数据的完整性。

注意,元组的元素不能修改,指的是元组当前的元素,如果元素本身是 一个列表,那么列表中的元素是可以修改的,比如下面这段代码:

tup = ([1,2,3],1,2)
tup[0][1]=4
print(tup)

# output:
# ([1, 4, 3], 1, 2)

3. 列表与元组总结

列表和元组,都是一个可以放置任意数据类型的有序集合。在绝大多数编程语言中,集合内的数据类型必须一致,但是对于Python的列表和元组来说,并无此要求。

它们的区别是:

  • 列表是动态的,长度大小不固定,可以随意地增加、删改或者修改其中的元素(mutable)。
  • 元组是静态的,长度大小固定,不可以增加、删改或者修改其中的元素(immutable),想对已有的元组做任何”改变”,就只能重新开辟一块内存,创建新的元组了。
  • 列表和元组两者可以通过list()tuple()函数相互转换。

列表和元组的性能比较:

元组要比列表更加轻量级一些,所以总体上来说元组的性能速度要略优于列表。另外Python会在后台,对静态数据做一些资源缓存(resource caching)。通常来说,因为垃圾回收机制的存在,如果一些变量不被使用了,Python就会回收它们所占用的内存并返还给操作系统,以便其他变量或其他应用使用。但是对于一些静态变量,比如元组,如果它不被使用并且占用空间不大时,Python会暂时缓存这部分内存。这样,下次我们再创建同样大小的元组时,Python就可以不用再向操作系统发出请求,去寻找内存,而是可以直接分配之前缓存的内存空间,这样就能大大加快程序的运行速度。

下面的例子,是计算初始化一个相同元素的列表和元组分别所需的时间。可以看到,元组的初始化速度,要比列表快5倍:

import timeit
print("The time taken is ",timeit.timeit(stmt='x=(1,2,3,4,5,6)'))
print("The time taken is ",timeit.timeit(stmt='x=[1,2,3,4,5,6]'))

# output:
# The time taken is  0.019765700000000663 
# The time taken is  0.06865189999999899

但如果是索引操作的话,两者的速度差别非常小,几乎可以忽略不计。

思考:创建空列表有以下两种方式,哪一种更快一些?

empty_list = list()
empty_list = []

上面两种方式的区别主要在于list()是一个函数调用(function call),Python的function call会创建栈stack,并且进行一系列参数检查的操作,比较expensive,反观[]是一个内置的C函数,可以直接被调用,因此效率更高。

4.序列概念与分类

序列是一种可迭代对象,可以存储多个数据,并提供数据的访问。序列中的数据,我们称为序列的元素。Python中,内置的序列类型有:

  • 列表(list)
  • 元组(tuple)
  • 字符串(str)
  • 字节(bytes)

序列支持如下通用操作:

  • 索引 通过索引可以访问序列中指定位置的元素(单个)。
  • 切片 通过切片可以访问序列中一个区间的元素(多个)。
  • 迭代 序列作为可迭代对象,因此,可以通过for循环进行遍历。
  • 长度 可以通过len函数获取序列的长度(序列中含有元素的个数)。
  • 运算 序列支持+,*,in,not in,比较,布尔运算符。

序列相关函数:

Python也提供了相应的函数,能够用于根据已经存在的可迭代对象(序列类型都是可迭代类型)创建新的序列类型,实际上,从另一个角度来讲,也就相当于进行了类型转换。

list() / list(iterable)
tuple() / tuple(iterable)
str() / str(object)
bytes() / bytes(str)
len(obj)
max(iterable, *[, default=obj, key=func]) / max(arg1, arg2, *args, *[, key=func])
min(iterable, *[, default=obj, key=func]) / min(arg1, arg2, *args, *[, key=func])
sum(iterable, start=0)
sorted(iterable, key=None, reverse=False)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值