上一篇文章 python学习——【第四弹】中我们学习了不可序列 字符串和可变序列 列表;这篇文章我们接着学习python中的不可变序列 元组。
元组是python内置的数据结构之一, 有序,可多种不同数据类型的元素混合存储,允许有重复数据,是不可变序列(所以没有元组生成式)。
1 直接小括号 yuanzu=(‘hello’,‘world’,10)
2 使用内置函数tuple() yuanzu=tuple((‘python’,‘hello’,0))
3 注意:只包含一个元组的元素需要使用逗号和小括号 yuanzu=(‘helloworld’,)
不加逗号会认为是 str类型。
yuanzu=('hello','world',90)
print(yuanzu,type(yuanzu)) #('hello', 'world', 90)
# 省略小括号创建元组
yuanzu1='hello','world',90
print(yuanzu1,type(yuanzu1)) #('hello', 'world', 90)
yuanzu3=('helloworld',)
print(yuanzu3,type(yuanzu3)) #('helloworld',)
# 使用函数tuple()
yuanzu2=tuple(('hello','world',80))
print(yuanzu2,type(yuanzu2)) # ('hello', 'world', 80)
# 生成元组
list1=[1, 2, 3, 4]
list2=['a', 'b', 'c', 'd']
new_list=zip(list1, list2) # 转换成一个zip对象
print(new_list, type(new_list)) #
dic=tuple(new_list) # 将zip对象转换为元组,嵌套中的元组是对应位置元素的两两结合
print(dic, type(dic)) # ((1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'))
# 空元组的创建方式
yuanzu4=()
yuanzu5=tuple()
print('空元组是',yuanzu4,yuanzu5) #空元组是 () ()
元组是有序序列
,可以通过索引号
来访问元组中的元素
yuanzu= ('hello','python','hello','world')
print(yuanzu[1]) # python
yuanzu= ('hello','python',80,'world')
print(80 in yuanzu) # True
print('hello' in yuanzu) # True
print(100 in yuanzu) # False
yuanzu= ('hello','python',80,'world')
print(len(yuanzu)) # 4
使用操作符 +
yuanzu1 = (10,30,'hello')
yuanzu2 = (99,'python')
yuanzu3 = yuanzu1 + yuanzu2
print(yaunzu3) # (10, 30, 'hello', 99, 'python')
元组中的某个特定的元素无法删除,可以使用del关键字将整个元组对象删除
t = ('hello','python',80,'world')
del t
print(t) # NameError: name 't' is not defined. Did you mean: 't1'? 已经删除元组
元组属于可迭代对象,依然可以使用 for —in 循环
yuanzu = tuple(('haha', 'lili', 'mimi'))
for item in yuanzu:
print(item)
'''
haha
lili
mimi
'''
注意事项:
元组中存储的是对象的引用 ; 如果元组中对象本身是不可变对象
,则不能再引用其他对象
;如果元组中对象本身是可变对象
,则可变对象的引用(id地址)不允许改变,但数据可以改变
如何理解呢?
我们知道不可变对象只允许查看,如果对其进行修改等操作会改变不可变对象的引用(id地址),假如元组中的不可变对象的引用改变了,那么元组的id地址也会发生变化; 而可变对象在进行修改操作后的引用是不发生改变的,因此元组中对象如果是可变对象的话,对其进行修改不会改变元组的id地址。
我们可以举几个例子看一下
# 举例
yuanzu=(10,'hello world',[11,22,'lisa'])
print('原元组的信息:',yuanzu,type(yuanzu),id(yuanzu))
print(yuanzu[0],type(yuanzu[0]),id(yuanzu[0]))
print(yuanzu[1],type(yuanzu[1]),id(yuanzu[1]))
print(yuanzu[2],type(yuanzu[2]),id(yuanzu[2]))
# 尝试修改yuanzu中的不可变元素
print('修改元组的不可变元素:')
yuanzu[0]=100
print(yuanzu) #不可修改 TypeError: 'tuple' object does not support item assignment
# 修改元组指向的列表为其他元素
print('修改元组中的列表为其他元素:')
yuanzu[2]='lisa'
print(yuanzu) #不可修改 TypeError: 'tuple' object does not support item assignment
# 通过修改元组中的列表元素来更改列表中的元素;由于列表是可变对象,对列表实现增删改不会产生
#列表对象:修改前后的内存地址不变,则元组的内存地址也不会发生改变
print('修改列表中的元素前列表信息:',yuanzu[2],id(yuanzu[2]))
yuanzu[2].append('tom')
print('修改元组中列表中的元素后,列表信息为:',yuanzu[2],id(yuanzu[2]))
print('修改元组中列表对象中的元素后的元组信息:',yuanzu,type(yuanzu),id(yuanzu))
但是当我们尝试去修改元组中的不可变序列(字符串)或者是直接修改引用列表元素的地址时,发现程序抛出 TypeError: ‘tuple’ object does not support item assignment 的错误
当然也可以将元组转换成列表,然后修改列表,再将修改的列表转换成元组,但要注意这样会产生一个新的元组。
t = ('hello','python',80,'world')
print('转换前的元组:',t,type(t),id(t))
lst = list(t) # 将元组转换为列表
print('转换成列表:',lst,type(lst))
lst[1] = 999
t1 = tuple(lst)
print('从列表转换成的元组:',t1,type(t1),id(t1))
从元组的这一特点我们也可以看出:
在程序中要尽量使用不可变序列;因为一旦创建了不可变对象,对象内部的所有数据就都不能被修改,这样可以避免由于修改数据而导致的错误;所以对于不可变对象,在多任务环境下,同时操作对象的时候就不需要加锁。
有志者事竟成!
如有不足感谢指正