python-数据类型-元组和列表
>元组和列表
>>元组
元组是不可修改的列表集合,为了定义数据的统一性,可以定义元组来对数据进行保存。
>>>元组定义
-
定义:
-
-
变量后面接的是 ()
-
括号内为空时,则是一个空元组
-
括号内只有一个元素时,则不为元组,由括号内元素类型定义
-
要想实现括号内只有一个元素的元组,则需要在该元素后面加入逗号","
# 定义一个空元组 info= (,) # 定义一个非空元组 info = (1,2,3,4)
-
>>>元组的特点
-
- 不能对元组进行修改/删除/插入元素操作,元组的内容是不能修改的
>>>命名元组
命名元组是比较特殊的元组,是可以修改的和操作的,命名元组可以和字典一样用键值对的形式将数据储存起来,然后可以用键的方式去取值。
命名元组的定义:
创建命名元组需要用到python中的namedtuple函数去实现。
from collections import namedtuple
info_tuple = namedtuple('info_tuple',['name','age','gendwe'])
tu = info_tuple('xianchen',18,'nan')
print(tu.name)
>>列表
>>>列表的定义
-
定义:
-
-
变量后面接的是 []
-
无论 [] 内为空或者只有单个/多个值时,都为列表
# 定义一个空列表 stu = [] # 定义一个非空列表 stu2 = ["zhangsan","lisi","wangwu"]
-
>>>列表的特点
-
特点:
-
- 支持对列表进行修改/删除/插入元素操作
>>>列表的索引
列表可以通过索引取值,列表序列的索引范围是从零开始的,最的的索引长度是”列表长度-1“。超出索引范围会提示IndexError。
通过正向索引取值
stu2 = ["zhangsan","lisi","wangwu"]
print(stu2[0])
>>> "zhangsan"
通过反向索引取值
反向索引是从-1开始,从列表最后一位数开始
stu2 = ["zhangsan","lisi","wangwu"]
print(stu2[-1])
>>> "wangwu"
通过索引修改数据
stu2 = ["zhangsan","lisi","wangwu"]
stu2[0]="wudaliang"
print(stu2)
>>> ["wudaliang","lisi","wangwu"]
>>>数据切片
列表往往保存了许多的数据,可以通过切片来获取一个范围内的数据,这个操作叫做列表的切片。
列表对象[开始索引:结束索引:步长]
>取数的范围:开始索引:结束索引 左闭右开 右边的索引位置数据不会取到
>步长 默认步长为1 ,如果步长为2 的话 就是隔两位数取一个
正切
number = [1,2,3,4,5,6,7,8,9]
print(number[3:7])
>>>[4, 5, 6, 7]
number = [1,2,3,4,5,6,7,8,9]
print(number[3:])
>>>[4, 5, 6, 7,8,9]
反切
number = [1,2,3,4,5,6,7,8,9]
print(number[0:-5])
>>>[1, 2, 3, 4]
number = [1,2,3,4,5,6,7,8,9]
print(number[:-1])
>>>[1,2,3,4,5,6,7,8]
跳级切
number = [1,2,3,4,5,6,7,8,9]
print(number[3:7:2])
>>>[4, 6]
反跳级切
number = [1,2,3,4,5,6,7,8,9]
print(number[0:-5:2])
>>>[1, 3]
number = [1,2,3,4,5,6,7,8,9]
print(number[-1:-5:-2])
>>>[9, 7]
>>>列表操作函数
extend(列表)将一个列表追加到另一个列表中
list_1=[1,2,3,4]
list_2=['小明','小红']
list_1.extend(list_2)
print(list_1)
>>>[1, 2, 3, 4, '小明', '小红']
copy列表数据复制
# 浅拷贝
list_2=['小明','小红',['xiaochen','xiaohua']]
list_3=list_2.copy() #list_3=copy.copy(list_2)
print(list_2,list_3)
# 深拷贝
list_1=['小明','小红',['xiaochen','xiaohua']]
list_4=copy.deepcopy(list_1)
print(list_2,list_3)
注意:此时会扯出深浅拷贝问题
以下是深浅拷贝解析
import copy
# 简单来说浅拷贝拷贝的时候,不管源列表是多少层,只拷贝其中的一层
# 定义list_2=['小明','小红',['xiaochen','xiaohua']] 并进行拷贝操作 查看两个列表的值相等
list_2=['小明','小红',['xiaochen','xiaohua']]
list_3=list_2.copy() #list_3=copy.copy(list_2)
print(list_2,"\n",list_3)
>>>['小明', '小红', ['xiaochen', 'xiaohua']]
['小明', '小红', ['xiaochen', 'xiaohua']]
# 第一步改变 list_2的值 list_2.append('1111') ,list_2值改变 ,list_3的值未改变
list_2 = ['小明', '小红', ['xiaochen', 'xiaohua']]
list_3 = list_2.copy() # list_3=copy.copy(list_2)
list_2.append('1111')
print(list_2, "\n", list_3)
>>> ['小明', '小红', ['xiaochen', 'xiaohua'], '1111']
['小明', '小红', ['xiaochen', 'xiaohua']]
# 第二步改变 list_3的值 list_3.append('22222') ,list_3值改变 ,list_2的值未改变
list_2 = ['小明', '小红', ['xiaochen', 'xiaohua']]
list_3 = list_2.copy() # list_3=copy.copy(list_2)
list_3.append('22222')
print(list_2, "\n", list_3)
>>>['小明', '小红', ['xiaochen', 'xiaohua']]
['小明', '小红', ['xiaochen', 'xiaohua'], '22222']
# 第三步改变 list_2[2]的值 list_2[2].append('我变了') ,list_2值改变 ,list_3的值改变
list_2 = ['小明', '小红', ['xiaochen', 'xiaohua']]
list_3 = list_2.copy() # list_3=copy.copy(list_2)
list_2[2].append('我变了')
print(list_2, "\n", list_3)
>>>['小明', '小红', ['xiaochen', 'xiaohua', '我变了']]
['小明', '小红', ['xiaochen', 'xiaohua', '我变了']]
# 第四步改变 list_3[2]的值 list_3[2].append('我也变了') ,list_3值改变 ,list_2的值改变
list_2 = ['小明', '小红', ['xiaochen', 'xiaohua']]
list_3 = list_2.copy() # list_3=copy.copy(list_2)
list_3[2].append('我也变了')
print(list_2, "\n", list_3)
>>>['小明', '小红', ['xiaochen', 'xiaohua', '我也变了']]
['小明', '小红', ['xiaochen', 'xiaohua', '我也变了']]
可以看出浅拷贝在拷贝嵌套的列表的时候,只拷贝了第一层,只有第一层是两个独立的对象,子对象并未发生改变,所以当子对象发生改变的时候,都会跟着改变。从内存地址来看子对象的内存地址并没有发生改变。
# 深拷贝 深拷贝无论你列表嵌套了多少层,都会将父对象和子对象拷贝出来,两个完全独立,子对象的内存地址和父对象的内对地址都是完成独立的,所以在改变子对象的数据时,不会改变之前的表
list_1= ['小明', '小红', ['xiaochen', 'xiaohua']]
list_4=copy.deepcopy(list_1)
# 改变list_1
list_1.append(1)
print(list_1,list_4)
>>>['小明', '小红', ['xiaochen', 'xiaohua'], 1] ['小明', '小红', ['xiaochen', 'xiaohua']]
# 改变list_1[2]
list_1[2].append(11)
print(list_1,list_4)
>>>['小明', '小红', ['xiaochen', 'xiaohua', 11]] ['小明', '小红', ['xiaochen', 'xiaohua']]
# 改变list_4
list_4.append(22)
print(list_1,list_4)
>>>['小明', '小红', ['xiaochen', 'xiaohua']] ['小明', '小红', ['xiaochen', 'xiaohua'], 22]
# 改变list_4[2]
list_4[2].append(333)
print(list_1,list_4)
>>>['小明', '小红', ['xiaochen', 'xiaohua']] ['小明', '小红', ['xiaochen', 'xiaohua', 333]]
无论是嵌套的列表发生改变还是原列表发生改变,都不会互相影响
remove列表数据删除
remove 需要明确知道数据才能删除
list_1= ['小明', '小红', ['xiaochen', 'xiaohua']]
list_1.remove('小明')
print(list_1)
>>>['小红', ['xiaochen', 'xiaohua']]
del删除数据
del 根据索引删除数据的
list_1= ['小明', '小红', ['xiaochen', 'xiaohua']]
del list_1[0]
print(list_1)
>>>['小红', ['xiaochen', 'xiaohua']]
pop列表内容弹出
list_1= ['小明', '小红', ['xiaochen', 'xiaohua']]
list_2=list_1.pop() # 默认弹出最后一位 弹出后列表长度改变 pop函数是有返回的 返回弹出的函数
print(list_1)
print(list_2)
>>>['小明', '小红']
['xiaochen', 'xiaohua']
--也可以根据索引弹出数据
list_1= ['小明', '小红', ['xiaochen', 'xiaohua']]
list_2=list_1.pop(0)
print(list_1,'\n',list_2)
>>>['小红', ['xiaochen', 'xiaohua']]
小明
append列表数据追加
list_1= ['小明', '小红', ['xiaochen', 'xiaohua']]
list_1.append('11')
print(list_1)
# 数据追加到 list_1最后面
sort列表的排序
list_1=[1,3,4,2,1,3,4,5,6,7,8]
list_1.sort()
print(list_1)
>>>[1, 1, 2, 3, 3, 4, 4, 5, 6, 7, 8]
reverse()列表的反转
list_1=[1,3,4,2,1,3,4,5,6,7,8]
list_1.reverse()
print(list_1)
>>>[8, 7, 6, 5, 4, 3, 1, 2, 4, 3, 1]
count统计列表指定内容出现的次数
list_1=[1,3,4,2,1,3,4,5,6,7,8]
print(list_1.count(1))
>>>2
index列表数据查找
list_1=[1,3,4,2,1,3,4,5,6,7,8]
li=list_1.index(3) # 查找数据3 返回的是索引的位置 否则就产生异常
print(li)
>>>1
>>列表推导式
# 语法 可以快速生成一个列表 out_list = [out_express for out_express in input_list if out_express_condition]
list = [i for i in range(10)]
print(list)
>>>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
'''
原理就是
evens = []
for i in range(10):
if i % 2 == 0:
evens.append(i)
'''
>>元组列表性能分析
# timeit 可以用来测试一个函数的运行时间,传参函数只需要传函数名,传字符类型需要传字符串
import timeit
t1 = timeit.Timer('[1,2,3]').timeit(1000)
t2 = timeit.Timer('(1,2,3)').timeit(1000)
if t1 < t2:
print('创建列表的时间比创建元组的小')
else:
print('创建列表的时间比创建元组的大')
>>>创建列表的时间比创建元组的大