小白如何成为python数据分析师
第九天----元组
列表和元组都是容器型的数据类型,即一个变量可以保存多个数据。列表是可变数据类型,元组是不可变数据类型,所以列表添加元素、删除元素、清空、排序等方法对于元组来说是不成立的。
只可读,定义元组通常使用
()
字面量语法。优势:不可变类型更适合多线程环境,
不可变类型在创建时间和占用空间上面都优于对应的可变类型
定义
在Python中,元组也是多个元素按照一定的顺序构成的序列。元组和列表的不同之处在于,元组是不可变类型,这就意味着元组类型的变量一旦定义,其中的元素不能再添加或删除,而且元素的值也不能进行修改。定义元组通常使用()
字面量语法,也建议大家使用这种方式来创建元组。元组类型支持的运算符跟列表是一样。
元组的相关操作
# 创建元组(自变量语法)
fruits = ('h', 'k', 'u', 'p', 'f',)
print(type(fruits))
# 重复计算
print(fruits * 3)
# 合并运算
fruits1 = ('5', '8', '7')
fruits3 = fruits1 + fruits
print(fruits3)
# 切片,索引
print(fruits[2:])
print(fruits3[::-1])
# 索引
print(fruits[-1])
print(fruits[3])
# 读取元素个数,元素位置(下标)
print(fruits3.index('5'))
print(fruits3.count('5'))
# 查看变量的类型
print(type(fruits)) # <class 'tuple'>
# 查看元组中元素的数量
print(len(fruits)) # 5
# 通过索引运算获取元组中的元素
print(fruits[0], fruits[-5]) # h h
print(fruits[3], fruits[-2]) # p p
# 循环遍历元组中的元素
for x in fruits:
print(fruits)
一个元组中如果有两个元素,我们就称之为二元组;一个元组中如果五个元素,我们就称之为五元组。以此类推;
’‘()’‘表示空元组,但是如果元组中只有一个元素,需要加上一个逗号,否则
()
就不是代表元组的字面量语法,而是改变运算优先级的圆括号,所以('hello', )
和(100, )
才是一元组,而('hello')
和(100)
只是字符串和整数。
# 空元组
a = ()
print(type(a)) # <class 'tuple'>
# 不是元组
b = ('hello')
print(type(b)) # <class 'str'>
c = (100)
print(type(c)) # <class 'int'>
# 一元组
d = ('hello', )
print(type(d)) # <class 'tuple'>
e = (100, )
print(type(e)) # <class 'tuple'>
元组的应用
1:打包和解包操作。
解包:(将元组的元素拆分。)当我们把一个元组赋值给多个变量时,元组会解包成多个值然后分别赋给对应的变量。解包语法对所有的序列都成立,这就意味着对字符串、列表以及我们之前讲到的range
函数返回的范围序列都可以使用解包语法。
打包:(将多个元素合拢成元组)元组当我们把多个用逗号分隔的值赋给一个变量时,多个值会打包成一个元组类型
# 打包
a = 1, 5, 6, 8, 10, 12
print(type(a), a) # <class 'tuple'> (1, 5, 6, 8, 10, 12)
# # 解包
a, b, c = (5, 6, 8)
print(a)
print(b)
print(c)
在解包时,如果解包出来的元素个数和变量个数不对应,会引发ValueError
异常,错误信息为:too many values to unpack
(解包的值太多)或not enough values to unpack
(解包的值不足)。
a, b, c = (5, 6, 8, 7, 20)
print(a)
print(b)
print(c)
解决方法:解决变量个数少于元素可以使用星号表达式’‘*’‘。
# *c 将剩下的归为一个列表都给c
a, b, *c = (5, 6, 8, 7, 20)
print(a) # 5
print(b) # 6
print(c) # [8,7,20]
# 取开头和结尾
a, *b, c = (5, 6, 8, 7, 20)
print(a)
print(c)
#取最后两个
*a, b, c = (5, 6, 8, 7, 20)
print(b)
print(c)
解包语法对所有的序列都成立,这就意味着对字符串、列表以及我们之前讲到的range
函数返回的范围序列都可以使用解包语法。
a, b, *c = range(1, 10)
print(a, b, c)
a, b, c = [1, 10, 100]
print(a, b, c)
a, *b, c = 'hello'
print(a, b, c)
2:交换两个变量的值
交换两个变量的值是编程语言中的一个经典案例,在很多编程语言中,交换两个变量的值都需要借助一个中间变量才能做到,如果不用中间变量就需要使用比较晦涩的位运算来实现。在Python中,交换两个变量
a
和b
的值只需要使用如下所示的代码。
a, b = b, a
a, b, c = b, c, a
但是如果有多于三个变量的值要依次互换,这个时候没有直接可用的字节码指令,执行的原理就是我们上面讲解的打包和解包操作。
# 交换
a, b = b, a
a, b, c = b, c, a
d = 0
a, b, c, d = b, c, d, a
3:让函数返回多个值。
有的时候一个函数执行完成后可能需要返回多个值,这个时候元组类型应该是比较方便的选择。例如,编写一个找出列表中最大值和最小的函数
# def定义一个函数;find_max_and_min(函数名);items(变量名)
def find_max_and_min(items):
"""找出列表中最大和最小的元素
:param items: 列表
:return: 最大和最小元素构成的二元组
"""
max_one, min_one = items[0], items[0]
for item in items:
if item > max_one:
max_one = item
elif item < min_one:
min_one = item
return max_one, min_one
# max_num, min_num 通过调用这个函数,输入变量items = [1, 3, 5, 8]
max_num, min_num = find_max_and_min([1, 3, 5, 8])
print(max_num, min_num)
上面函数的return
语句中有两个值,这两个值会组装成一个二元组然后返回。所以调用find_max_and_min
函数会得到这个二元组,如果愿意也可以通过解包语法将二元组中的两个值分别赋给两个变量。
4.元组和列表的比较
这里还有一个非常值得探讨的问题,Python中已经有了列表类型,为什么还需要元组这样的类型呢?
-
元组是不可变类型,不可变类型更适合多线程环境,因为它降低了并发访问变量的同步化开销。关于这一点,我们会在后面讲解多线程的时候为大家详细论述。
-
元组是不可变类型,通常不可变类型在创建时间和占用空间上面都优于对应的可变类型。我们可以使用
sys
模块的getsizeof
函数来检查保存相同元素的元组和列表各自占用了多少内存空间。我们也可以使用timeit
模块的timeit
函数来看看创建保存相同元素的元组和列表各自花费的时间,代码如下所示。
import sys
import timeit
a = list(range(100000))
b = tuple(range(100000))
print(sys.getsizeof(a), sys.getsizeof(b)) # 900120 800056
print(timeit.timeit('[1, 2, 3, 4, 5, 6, 7, 8, 9]'))
print(timeit.timeit('(1, 2, 3, 4, 5, 6, 7, 8, 9)'))
Python中的元组和列表是可以相互转换的,我们可以通过下面的代码来做到。
# 将元组转换成列表
info = ( 175, True, '好人')
print(list(info)) # [175, True, '好人']
# 将列表转换成元组
fruits = ['apple', 'banana', 'orange']
print(tuple(fruits)) # ('apple', 'banana', 'orange')