python数据类型之列表(一)
主要讲解列表的特点、内置方法、切片等,纯手码
一、特点:
①是可变类型,可以直接修改原列表
②是有序集合
二、列表常用操作
1、insert()
lst = ['张三', '王五']
# 指定索引前插入,lst.insert()没有返回值
lst.insert(1, '李四')
print(lst) # >>>['张三', '李四', '王五']
2、append()
lst = ['张三', '王五']
# 末尾插入,lst.append()没有返回值
lst.append('李四')
print(lst) # >>>['张三', '王五', '李四']
3、extend()
# 末尾插入,无返回值,功能比append强大很多。类似列表拼接,但是跟拼接的区别是extend修改了原列表;拼接生成的是新列表,效率较低
lst1 = ['a', 'b', 'c']
lst1.extend('dd') # 分解字符串插入
lst1.extend(['dd']) # 完整字符串插入
lst1.extend(('ef')) # 分解元组插入
lst1.extend([('ef')]) # 完整元组插入
print(lst1) # >>>['a', 'b', 'c', 'd', 'd', 'dd', 'e', 'f', 'ef']
4、pop()
# 默认删除末尾元素,也可指定索引删除。有返回值,返回被删除元素
lst1 = ['a', 'b', 'c', 'd']
a = lst1.pop()
b = lst1.pop(0)
print('删除后:%s,删除末尾:%s,删除指定:%s' % (lst1, a, b))
# >>>删除后: ['b', 'c'] 删除末尾: d 删除指定: a
5、remove()
# 删除被指定的第一个元素。有返回值
lst1 = ['a', 'b', 'c', 'd', 'c']
lst1.remove('c')
print(lst1) # >>>['a', 'b', 'd', 'c']
6、del
# 指定索引删除。无返回值
lst1 = ['a', 'b', 'c', 'd', 'c']
del lst1[0]
print('删除后:', lst1) # >>>删除后: ['b', 'c', 'd', 'c']
7、sort()
# sort(key=None,reverse=False) 排序,默认升序,对原列表进行了修改
# 默认用法,升序
lst1 = [888, 12, 999]
lst1.sort() # reverse默认False
print(lst1)
# 降序
lst1 = [888, 12, 999]
lst1.sort(reverse=True)
print(lst1)
# 使用key参数
lst1 = [[888, 12], [12, 55], [999, 63], [13, 31]]
lst1.sort(key=lambda x: x[1]) # 将每个列表中的第二个元素给key再排序,拿到的结果是:12,55,63,31
print(lst1)
# >>>[[888, 12], [13, 31], [12, 55], [999, 63]]
8、sorted()
# sorted(iterable, cmp=None, key=None,reverse=False) 对所有可迭代的对象进行排序,返回排好序的列表,不会对原列表进行修改
# 返回排好序的新列表
lst1 = [888, 12, 999]
for i in sorted(lst1):
print(i)
# 使用key参数
lst1 = [[888, 31], [12, 23], [999, 41]]
new_lst = sorted(lst1, key=lambda x: x[1])
print('原列表:%s\n新列表:%s' % (lst1, new_lst))
# >>> 原列表:[[888, 31], [12, 23], [999, 41]]
# >>> 新列表:[[12, 23], [888, 31], [999, 41]]
9、reserve()
# 翻转列表。无返回值
lst = ['a', 'b', 'c']
lst.reverse()
print(lst) # >>>['c', 'b', 'a']
10、reversed()
# reserved(seq) 返回一个反向的迭代器,seq为要转换的序列,可为list,string,tuple,range
# list
lst1 = ['a', 'b', 'c']
a = list(reversed(lst1)) # 将迭代器用列表包起来
print(a) # >>>['c', 'b', 'a']
# string
str1 = 'qwe'
a = list(reversed(str1)) # 将迭代器用列表包起来
print(a) # >>>['e', 'w', 'q']
# tuple
tup1 = ([1, 2], [3, 4])
a = list(reversed(tup1)) # 将迭代器用列表包起来
print(a) # >>>[[3, 4], [1, 2]]
# range
ran1 = range(1, 4)
a = list(reversed(ran1)) # 将迭代器用列表包起来 print(a)
print(a) # >>>[3, 2, 1]
11、clear()
# 清空列表所有元素,无返回值
lst1 = ['a', 'b', 'c']
lst1.clear()
print(lst1) # >>>[]
12、index()
# 获取指定元素的索引,有返回值,返回索引
lst1 = ['a', 'b', 'c']
a = lst1.index('a')
print(a) # >>>0
13、count()
# 获取指定元素出现的次数,有返回值,返回次数
lst1 = ['a', 'b', 'c']
a = lst1.count('a')
print(a) # >>>1
14、copy()与deepcopy() -浅拷贝与深拷贝
14.1 浅拷贝
import copy
# 浅拷贝1(赋值引用)
lst1 = [1, 2, 3]
lst2 = lst1 # 指向同一内存地址
if lst1 is lst2: # True
lst2.append(4)
print("浅拷贝1(赋值引用):", lst1) # >>>[1, 2, 3, 4]
print("浅拷贝1(赋值引用):", lst2) # >>>[1, 2, 3, 4]
# 浅拷贝2(copy)
# 注意点1、copy.copy对于拷贝的整个对象,两者指向不同内存,两者独立 --深拷贝
lst3 = [0, [123]]
lst4 = copy.copy(lst3)
if not (lst3 is lst4): # not False
print("copy的整个对象,两者内存不一样")
lst4.append([456])
print("copy之父对象相互独立:", lst3) # >>>[0, [123]]
print("copy之父对象相互对立:", lst4) # >>>[0, [123], [456]]
# 注意点2、copy.copy对于拷贝的对象中如果存在不可变类型元素(数字、字符串、元组),拷贝前后的两个不可变元素指向相同内存,但是两者仍然独立 --深拷贝
lst5 = [0, [123]]
lst6 = copy.copy(lst3)
if lst5[0] is lst6[0]: # True
print("拷贝前后两个不可变类型元素的内存一样")
lst6[0] = 1 # 0是不可变类型
print("copy之父对象的可变子对象相互独立:", lst5) # >>>[0, [123]]
print("copy之父对象的可变子对象相互独立:", lst6) # >>>[1, [123], [456]]
# 注意点3、copy.copy对于拷贝的对象中如果存在可变类型(列表、字典、集合),拷贝前后的两个可变类型的元素指向相同内存,两者元素的值互相影响 --浅拷贝
lst7 = [0, [123]]
lst8 = copy.copy(lst7)
lst8[1].append(4) # [123]是可变类型,修改lst8后,lst7也会变化
print("copy之父对象的不可变子对象被浅拷贝:", lst7) # >>>[1, [123, 4]]
print("copy之父对象的不可变子对象被浅拷贝:", lst8) # >>>[1, [123, 4]]
14.2 深拷贝
import copy
# 深拷贝(赋值引用)
lst1 = ['a', 'b', 'c']
lst2 = lst1[:] # 申请新的内存地址,然后复制
if not (lst1 is lst2): # 判断内存地址是否不一样,>>>True
lst2.append('d') # 修改lst2,lst1不会被修改
print(lst1) # ['a', 'b', 'c']
print(lst2) # ['a', 'b', 'c', 'd']
# 深拷贝(deepcopy)
lst3 = ['a', 'b', ['ab']]
lst4 = copy.deepcopy(lst3)
if not (lst3 is lst4): # not False 判断整个对象的内存是否不一样
if not (lst3[0] is lst4[0]): # not False 判断整个对象中的的不可变类型的元素的内存是否不一样
if not (lst3[2] is lst4[2]): # not False 判断整个对象中的可变类型的元素的内存是否不一样
print("深拷贝对于对象中的元素都会重新申请新的内存,拷贝前后的对象没有任何关系")
14.3 copy和deepcopy的原理及应用
A、copy.copy()
①copy整个对象的时候:申请了一个新的内存地址,所以对copy后的整个对象进行增删元素的操作就不会影响copy前的对象(这个特性有点类似深拷贝)
②copy整个对象中的元素的时候:会区分元素类型是否是可变,如果是不可变的元素,copy的时候不申请新内存,和被copy的元素对象指向同一内存,但是修改copy后的元素,不会影响copy前的元素(这个特性有点类似深拷贝)
③copy整个对象中的元素的时候:会区分元素类型是否是可变,如果是可变的元素,copy的时候不申请新内存,和被copy的元素对象指向同一内存,但是修改copy后的元素,copy前的元素也会被修改
B、copy.deepcopy()
不管是整个对象,还是整个对象中的元素,deepcopy的时候都会申请新的内存地址,deepcopy前后的对象互不干涉
C、应用
import copy
lst1 = [1, 2, 3]
num_lst = [4, 5]
lst1.append(num_lst) # 浅拷贝,赋值引用,相当于将num_lst直接赋值给一个对象后再插入到lst1
num_lst.clear() # 此时清空num_lst
print(lst1) # 发现lst1中的元素也被修改 >>>[1, 2, 3, []]
lst1 = [1, 2, 3]
num_lst = [4, 5]
lst1.append(copy.deepcopy(num_lst)) # 申请新的内存,将新的对象插入lst1
num_lst.clear() # 此时清空num_lst
print(lst1) # 发现lst1中的元素不会被修改 >>>[1, 2, 3, [4, 5]]

浙公网安备 33010602011771号