python—之列表的学习

1. 列表

对于python列表的理解可以和C语言里面的数组进行比较性的记忆与对照,它们比较相似,对于python里面列表的定义可以直接用方括号里加所包含对象的方法,并且python的列表是比较强大的,它包含了很多不同类型的数据:整型数字,浮点型,字符串以及对象等。
不同于 C++ 和 Java,在 Python 中,没有在标准库中内置数组类型,而是通常利用列表来表示数组,同时它也比数组的使用要灵活得太多。
列表是 Python 中最基本的数据结构,列表中的元素的存储是有序的,所以我们可以直接利用索引去访问列表中的值。在学习数据结构时,我们知道,对一个数据结构的操作,无外乎增删改查四种。接下来本文将从这四个方面来介绍列表的一些常用小技巧。

1.1. 列表中的增

对列表的增加操作有两种,一种是创建一个新的列表,一种是在一个已有的列表中增加一个新元素。我们首先介绍如何创建一个新的列表:

 # 创建一个空列表
 list1 = []
 # 创建一个默认值为0,长度为n的列表
 list2 = [0] * n
 # 利用列表生成式创建列表
 list3 = [i for i in range(10)]
 # 5*5 二维列表
 list4 = [[i for i in range(5)] for j in range(5)]
 # 利用其他数据结构生成列表, list() 函数接收一个可迭代对象作为参数
 tuple1 = (1, 2, 3)list5 = list(tuple1)
 # 字符串转化为列表str1 = "I love code"
 # 每个元素作为列表中的一个元素list6 = list(str1)
 # 按照指定字符分割list7 = str1.split(" ")
 # ['I', 'love', 'code']

在编程过程中,有时我们需要对一个列表进行操作,但是列表是一个可变对象,对列表的操作往往会改变其本来的顺序结构。因此,当我们不想改变列表原有的顺序结构,我们需要对旧的列表进行一个拷贝,然后在新的列表上进行操作。拷贝存在两种,浅拷贝和深拷贝
两种拷贝后得到的列表形式确实是一样的。但是在进行操作时,就会有很大的差别了,特别是当你的列表中存在可变对象时。我们只需要记住一点,浅拷贝只复制不可变对象,而深拷贝不仅复制不可变对象,还复制了可变对象。以下进行举例说明:

# 如果一个列表中的元素都是不可变对象,可以直接用浅拷贝
list1 = [1, 2, 'i']
list2 = list1[::1]                               # 浅拷贝
list3 = [i for i in list1]                       # 浅拷贝
import copy
list4 = copy.copy(list1)                         # 浅拷贝 
# 如果一个列表中的元素包含可变对象,要完成复制列表,需要用深拷贝
list5 = ["Will", 1, ["Python", "Java", "C++"]]
list6 = copy.deepcopy(list5)

浅拷贝只拷贝不可变对象。当列表中存在可变对象时,我们可以发现其引用 id 是一样的,即它们是同一个对象,因此对 list5 的操作会影响到 list6 。而在深拷贝中,对于可变对象,在拷贝的新列表中会生成一个新的对象,所以对 list6 的修改不会影响到 list5 。

id(list5[2])              # 2195936916360
id(list6[2])              # 2195936916744

对列表的另一种增加操作就是在已有的列表的基础上增加元素了,主要包括以下几种操作:

list1 = ["I"]
# 在列表尾部增加一个新元素
list1.append("love")
# 合并两个列表
list2 = ["Apple", 3]list1.extend(list2)         # ["I", "love", "Apple", 3]
list1 = list1 + list2                           # ["I", "love", "Apple", 3]
# 在指定位置插入元素
list1.insert(index=1, "not")                    # ["I", "not", "love", "Apple", 3]

1.2. 列表中的删

对数据结构的删除操作包括两种,删除整个列表,或者删除列表中的某些元素。对于从内存中删除整个列表,该操作十分简单:

list1 = [1, 2, 3]
del list1

对于删除列表中的元素,同样可以使用 del 语句,同时还可以使用 remove() 函数。

list1 = [1, 2, 3]
print(list1)             # [1, 2, 3]
del list1[1] 
print(list1)             # [1, 3]
 
# 移除某个值的第一匹配项
list2 = [1, 2, 2, 3, 5]
list2.remove(2)          # 移除第一个值为 2 的元素

1.3. 列表中的改

修改操作即在原有的列表的基础上对其进行修改,上面以及介绍了增加和删除操作,这里就对不改变元素的个数的操作进行介绍,主要包括排序和反转列表等。

# 对一个整数列表进行排序
list1 = [9, 5, 6, 2, 7, 1, 3]
# 升序排列list1.sort()              # [1, 2, 3, 5, 6, 7, 9]
list1 = sorted(list1)               # [1, 2, 3, 5, 6, 7, 9]
# 降序排列list1.sort(reverse=True)   # [9, 7, 6, 5, 3, 2, 1]
list1 = sorted(list1, reverse=True)  # [9, 7, 6, 5, 3, 2, 1] 
# 指定键值排序
list1 = [('a', 3), ('b', 2), ('c', 1)]
list1.sort(key=lambda x:x[1])         # [('c', 1), ('b', 2), ('a', 3)] 
## 反转列表,即将原来的列表逆序排列
list2 = [4, 2, 3, 1]
list2 = list2[::-1]                   # [1, 3, 2, 4]
list2.reverse()                       # [1, 3, 2, 4]

1.4. 列表中的查

对列表的查找操作无外乎以下几种:

遍历列表;
查找指定索引的元素;
查找指定值的元素;

列表的遍历方式有三种,分别是根据索引遍历、根据值遍历和 enumerate()遍历。

list1 = ["Python", "C++", "Java"] 
# 方法 1
for i in range(len(list1)):	
	print(list1[i]) 
# 方法 2 , 遍历速度最高效,但是无法记录索引
for i in list1: 
	print(i) 
 # 方法 3
for index, val in enumerate(list1): 
	print(val)

查找元素有两种,一种是按照索引查找,一种是遍历按值查找。

# 查找指定索引的元素
list1 = [1, 3, 2, 5, 7, 8]
list1[3]                   # 返回索引为 3 的元素,值为5
# 查找指定值的元素
key = 5
for i in list1:
if i == key: print("OK") 
# 查找最大元素和最小元素
max(list1)                  # 8
min(list1)                  # 1

列表结构的转化主要包括将列表转化为元组、集合、字符串和字典:

list1 = ["a", "b", "c", "d", "c"]
# 列表转化为元组
tuple1 = tuple(list1)                       # ('a', 'b', 'c', 'd', 'c') 
# 列表转化为集合set1 = set(list1)            # {'a', 'b', 'c', 'd'} 
# 列表转化为字符串str1 = "".join(list1)      # 'abcdc' 
# 列表转化为字典,元素为 key, 次数为 value
from collections import Counter, defaultdict
dict1 = Counter(list1)                    # Counter({'a': 1, 'b': 1, 'c': 2, 'd': 1})
# 或者dict2 = defaultdict(int)
for i in list1: 
	dict2[i] += 1 
dict2                                   # defaultdict(int, {'a': 1, 'b': 1, 'c': 2, 'd': 1})

总结:
1.由于python内部的引用计数的特性,对于不可变对象,浅拷贝和深拷贝的作用是一致的,就相当于复制了一份副本,原对象内部的不可变对象的改变,不会影响到复制对象。
2.浅拷贝和深拷贝。其实就是拷贝了原始元素的引用(内存地址),所以当拷贝可变对象时,原对象内可变对象的对应元素的改变,会在复制对象的对应元素上体现。
3.深拷贝遇到可变对象时,又在内部新建了一个副本,新分配了一个内存地址。所以内部的元素如何变化,都不会影响到原来的可变对象。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值