Python容器专题 - 列表(list)

简介: Python容器专题 - 列表(list)

Python容器专题 - 列表(list)


1. 快速入门列表

1.1 创建列表

【eg1-1】创建列表的常见方式汇总

a = []                            # 创建空列表
b = [1,2,3,4,5,'6',{7}]           # 创建拥有不同数据类型成员的列表
c = list((0,1))                   # 通过强制类型转换创建列表
d = ['零','一','二','三','四','五','六'][1:5]   # 通过列表的切片创建子列表
e = [i for i in range(1,16,2)]                 # 使用嵌套的表达式建立列表,用到了列表推导式的写法
f = list(map(lambda x: x, range(1,16,2)))      # 效果上与e相同
g = [[1,2,3,4,5],[5,4,3,2,1]]                  # 创建二维列表
print('\na=',a,'\nb=',b,'\nc=',c,'\nd=',d,'\ne=',e,'\nf=',f,'\ng=',g)

Out[]:

a= [] 
b= [1, 2, 3, 4, 5, '6', {7}] 
c= [0, 1] 
d= ['一', '二', '三', '四'] 
e= [1, 3, 5, 7, 9, 11, 13, 15] 
f= [1, 3, 5, 7, 9, 11, 13, 15] 
g= [[1, 2, 3, 4, 5], [5, 4, 3, 2, 1]]

另外,在创建列表时我们还可以用“list * num”的表达式简写重复的元素,例如:

【eg1-2】“list * num”的使用

[1,2] * 2

Out[2]:

[1, 2, 1, 2]

从结果中我们可以看到,“* 2”这一操作既没有升级为二维列表,也不是得到两个列表,更不是将原列表中所有的元素都X2,而仅仅是把原来列表中的元素原封不动且不改变顺序地插入了一遍。类似地,我们也可以在创建多维列表时使用该方法,如:

【eg1-3】通过“list * num”创建多维数组

[[1,2] * 2] * 3

Out[3]:

[[1, 2, 1, 2], [1, 2, 1, 2], [1, 2, 1, 2]]

这样创建地多列表组看起来好像和普通方法列表一样,特别是使用print()函数输出时,它似乎就是普通列表。但是在对其赋值时却会有让人预料外地结果:

【eg1-4】

a = [[1] * 2] * 3
a[0][1] = 3
a

Out[4]:

[[1, 3], [1, 3], [1, 3]]

这与我们所期待的结果[[1, 3], [1, 2], [1, 2]]似乎有那么些不同——由*3创建的所有子数组全部被赋值了而不仅仅是第一个子数组[1,2]赋值成[1,3]。很好!这就是这里要提示的一个知识点。

发生上述现象的原因在于使用 *对列表执行重复操作并不是创建副本,它只是创建现有对象的引用! *3 创建了对长度为二的同一列表的 3 个引用。 正是如此,对某一行的改变会作用于所有行。

基于以上的特性,在创建有相同子列表的列表时,先创建一个所需长度的列表,其相同子列表作为元素的部分使用*将显得容易,比如:

【eg1-5】

a = [1,2] * 2            # [1,2, 1,2]
for i in range(2):
    a[i] = [1,3] * 2
a

Out[5]:

[[1, 3, 1, 3], [1, 3, 1, 3], 1, 2]

1.2 列表索引与切片

【eg1-6】通过使用“[i]”实现列表的索引:

a = [1, 2, 3, 4]
a[-1]

Out[5]:

4

【eg1-7】通过使用“:”运算符实现列表的切片:

a = [1, 2, 3, 4]
a[0:1]

Out[6]:

[1]

1.3 列表的合并

【eg1-8】通过使用“+”运算符实现两个列表的合并:

a = [1, 2, 3, 4]
b = [5, 6, 7, 8]
a+b

Out[7]:

[1, 2, 3, 4, 5, 6, 7, 8]

也可以通过list.extend()方法实现两个列表的合并,详见下一节

1.4 元素存在性

a = ["老虎","狮子","豹子","袍子","猴子","猩猩","狗熊"]
"北极熊" in a               # 判断某元素是否在列表a中,结果为 False
“"猴子" in a                # 结果为 True
"袍子" not in a             # 结果为 False

1.5 统计列表

# 列表元素的统计
a = [i for i in 'ABCDEFGHIJKABCDEFGHIJK']
a.count('A')                               # 其结果为 2,表明该元素在列表中出现过2次

1.6 反转列表

# 反转
a = [1, 2, 3, 4, 5, 6, 7]
a.reverse()                               # 反转列表元素,[7, 6, 5, 4, 3, 2, 1]

1.7 列表排序

# 排序
a = [ 'zl赵六', 'lh李华', 'lm李明', 'xh小红','zs张三', 'lh李华', 'ww王五', 'zl赵六', 'xh小红', 'lh李华']
print(a.sort())     # 对列表中的元素进行排序
                    # 结果为 [‘lh李华’, ‘lh李华’, ‘lh李华’, ‘lm李明’, ‘ww王五’, ‘xh小红’, ‘xh小红’, ‘zl赵六’, ‘zl赵六’, ‘zs张三’]
b = [9,7,8,5,2,4,5,4,5]
b.sort()
print(b)           # 结果为 [2, 4, 4, 5, 5, 5, 7, 8, 9]

注意:列表的sort()方法本身并不返回值,它会改变原列表元素的顺序。如果仅想返回一个排序后的列表,可以使用sorted()语句,该语句不会改变原列而返回一个新的排序后的列表,如:

a = [9,7,8,5,2,4,5,4,5]
print("a=",a)
sorted(a)

1.8 拷贝列表

在Python语言中,拷贝可以分为深拷贝浅拷贝,列表(list)自带浅拷贝方法.copy()

# 获取列表的一个浅拷贝
a = [0, 1, 2, 3, 4, 3, 2, 1]
a.copy()

除此之外,你也可以使用Python的标准库copy来实现拷贝,如:

import copy
a = ["你","好"]
copy.copy(a)        # 返回对象a的浅拷贝
copy.deepcopy(a)    # 返回对象a的深拷贝

2 列表推导式

2.1 列表推导式的概念

列表推导式,又称列表生成式。用来创建(生成)列表的表达式就是列表推导式,它也称为列表生成式。

本质上列表推导式就是一个简写的for语句。列表推导式中最先出现的与快是后面for语句中遍历时的迭代量的函数,描述了最终返回的列表的每一个元素。每个列表推导式都在for语句后跟一个表达式,然后有若干个for或者if子句。返回结果是一个根据该简写的for语句块生成的列表。

2.2 通过列表推导式将方法应用于一系列对象

obj表示某个对象,method()是该对象的一个方法,其使用方法如:

result = [obj.method() for obj in mylist]

3. 列表的常用方法

3.1 列表元素的增删改以及索引

– 增 –

list.append(x) - 在列表的末尾添加一个元素。
  • 相当于 a[len(a):] = [x] 。

【eg1-9】使用列表的append()方法在末尾插入新元素

a = []
for i in range(19):
    a.append(i)
a

Out[8]:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
list.insert(i, x) - 在指定的位置插入一个元素。
  • 第一个参数是要插入的元素的索引,所以 a.insert(0, x) 插入列表头部, a.insert(len(a), x) 等同于 a.append(x) 。

【eg1-10】在某列表a的原第3号位置插入一个新元素

a = [0, 1, 2, 3, 4]
a.insert(3, '我是新来的')
a

Out[9]:

[0, 1, 2, '我是新来的', 3, 4]

【注意】:使用insert()方法进行插入时,以第一个参数为原先列表的索引值i一定是从0开始计算的。插入元素后,后面的元素先依次往后挪动出一个位置,直至原来在该位置的元素向后挪动出一个空位。最后才把新的元素放在这个唯一的空位上。

– 删 –

list.pop([i]) - 删除列表中给定位置的元素并返回它。
  • 如果没有给定位置,a.pop() 将会删除并返回列表中的最后一个元素。
  • 【注意】:方法签名中 i 两边的方括号表示这个参数是可选的,而不是需要你再调用的时候输入方括号,本文之后的类容中出现的所有可选区参数在表示上都将遵循该规则。

【eg1-11】

a = [0, 1, 2, 3, 4]
a.pop()          # pop()函数的返回值是出栈或被删除的元素

Out[10]:

4
a

Out[11]:

[0, 1, 2, 3]

【eg1-12】

a = [0, 1, 2, 3, 4]
a.pop(2)
a

Out[12]:

[0, 1, 3, 4]
list.remove(x) - 移除列表中第一个值为 x 的元素。
  • 如果没有这样的元素,则抛出 ValueError 异常。

【eg1-13】

a = [0, 1, 2, 3, 4, 3, 2, 1]
a.remove(3)
a

Out[13]:

[0, 1, 2, 4, 3, 2, 1]
list.clear() - 删除列表中所有的元素。
  • 相当于 del a[:] 。

【eg1-14】

a = [0, 1, 2, 3, 4, 3, 2, 1]
a.clear()
a

Out[14]:

[13]

– 改 –

list.extend(iterable) - 使用可迭代对象中的所有元素来扩展列表。
  • 相当于 a[len(a):] = iterable 。
我们上面已经介绍果了通过列表的加运算来实现列表的合并。
应该指出的是加运算符只能合并两个列表,而这里的extend()方法却适用于所有课迭代对象。

【eg1-15】使用list的extend()方法合并另一个列表对象:

a = [0, 1, 2, 3, 4]; b = ['5','6','7']
a.extend(b)
a

Out[15]:

[0, 1, 2, 3, 4, '5', '6', '7']

【eg1-16】使用list的extend()方法合并一个集合对象:

a = [0, 1, 2, 3, 4]; b = {'5','6','7'}
a.extend(b)
a

Out[16]:

[0, 1, 2, 3, 4, '5', '7', '6']

【注意】:使用extend()方法合并列表与合并集合有什么不同呢?细心观察上例的同学应该发现一个问题——合并后集合部分的顺序改变了!这里的原因是集合是无序的而列表是有序的。但需要指出的是这并不代表在合并时候合并是随机进行的!上面的代码无论执行多少次它将总是和你第一次所看到的执行结果相同。

【eg1-17】使用list的extend()方法合并一个字典对象:

a = [0, 1, 2, 3, 4]; b = {'5':'五','6':'六','7':'气'}
a.extend(b)
a

Out[17]:

[0, 1, 2, 3, 4, '5', '6', '7']

在这个例子中我们可以看到,合并时并不是合并某个键值对,而是依据字典原来顺序的所有键构成的列表。

– 反查索引 –

list.index(x[, start[, end]]) - 返回列表中第一个值为 x 的元素的从零开始的索引。
  • 在列表的“索引与切片”部分我们时通过由列表的索引值获取指定的元素或者子列表。然而这里与以上过程恰好时相反的,我们的目的是查询列表的索引
  • 如果没有这样的元素将会抛出 ValueError 异常。
  • 可选参数 start 和 end 是切片符号,用于将搜索限制为列表的特定子序列。返回的索引是相对于整个序列的开始计算的,而不是 start 参数。

【eg1-18】获取字符串’ABCDEFGHIJKABCDEFGHIJK’中第一个字母’G’的索引

a = [i for i in 'ABCDEFGHIJKABCDEFGHIJK']      # 一一映射字符串为列表
a.index('G')                       # 使用列表的index()方法查询'G'的索引

Out[18]:

6

【提醒】:第一个索引值是0。从第一个字母’A’开始,第1个字母’G’的索引是6,因此返回值是6。

【eg1-19】在字符串’ABCDEFGHIJKABCDEFGHIJK’中从第位置2开始寻找下一个字母’G’的索引

a = [i for i in 'ABCDEFGHIJKABCDEFGHIJK']
a.index('G', 7)

Out[19]:

17

【提示】:从第一个字母’A’开始,第1个字母’G’的索引是6,第2个字母’G’的索引是17。索引为7的字母是第1个’H’,它已经在第1个G后了,接下的的第1个’G’字母也就是第二个’G’字母,其索引值为17。

3.2 列表的拷贝方法

list.copy() - 返回列表的一个浅拷贝
  • 相当于 a[:] 。

【eg1-20】

a = [0, 1, 2, 3, 4, 3, 2, 1]
a.copy()

Out[20]:

[0, 1, 2, 3, 4, 3, 2, 1]

3.3 列表元素的统计

list.count(x) - 返回元素 x 在列表中出现的次数。

【eg1-21】

a = [i for i in 'ABCDEFGHIJKABCDEFGHIJK']
a.count('A')

Out[21]:

2

3.4 列表元素的排序和反转

list.sort(*, key=None, reverse=False) - 对列表中的元素进行排序
  • 其中参数可用于自定义排序,与sorted()函数类似。
  • 若reverse=True,则将在reverse=False的基础上将结果反转后返回。

【eg1-22】

a = [ 'zl赵六', 'lh李华', 'lm李明', 'xh小红','zs张三', 'lh李华', 'ww王五', 'zl赵六', 'xh小红', 'lh李华']
a.sort()
a

Out[22]: [‘lh李华’, ‘lh李华’, ‘lh李华’, ‘lm李明’, ‘ww王五’, ‘xh小红’, ‘xh小红’, ‘zl赵六’, ‘zl赵六’, ‘zs张三’]

list.reverse() - 反转列表中的元素。

【eg1-23】

a = [1, 2, 3, 4, 5, 6, 7]
a.reverse()
a

Out[23]:

[7, 6, 5, 4, 3, 2, 1]

3.5 交换二维列表的行和列(转置)

【eg1-24】当一个二维列表的每一个子列表拥有相同的长度时,可以视作一个矩阵。可以通过如下方法交换其行列:

# 定义一个矩阵类
class Matrix(object):
    def __init__(self,alist):
        self.__alist = alist
    def __str__(self):
        return str(self.__alist)
    def T(self):
        """矩阵的转置"""
        self.__alist = [[row[i] for row in self.__alist] for i in range(len(self.__alist[0]))]
        return self.__alist

下面传入一个列表来测试一下:

# 先定义一个列表
alist = [
    [1, 2, 3, 4],
    [5, 6, 7, 8],
    [9, 10, 11, 12],
]
# 将列表传入该矩阵类
matrix = Matrix(alist)
# 转字符串查看
str(matrix)

Out[24]:

'[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]'

接着测试一下行列互换

matrix.T()

Out[25]:

[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

5. 使用zip()函数对列表构建一一对应的可迭代对象

zip()函数接受任意多个可迭代对象,返回的是一个可以迭代的zip对象,如果在jupyter notebook中查看,则显示的内容形式如‘<zip at 0x13fd1e99f40>’。

先来看一个需求吧。从李华的一次期末考试说起吧:

# 考试科目
labels = ['语文','数学','英语','物理','化学','生物','政治']
# 横坐标(表示横轴位置、无含义)
x = [1,2,3,4,5,6,7]
# 纵坐标(考试得分)
y = [120,55,129,59,89,73,97]

考虑绘制一个bar图来表示李华各科的成绩以可视化呈现李华在不同科目上的表现,我们需要知道每一个科目在图上的位置。这意味着若当我们自己实现这样一个绘图库时我们需要将labels、x、 y三者的元素一一对应起来。如果没有zip()函数,我们可能需要这样做:

【eg1-25】不使用zip()函数时的实现方法

alist = []
for i in range(len(labels)):
    alist.append((x[i],y[i],labels[i]))
alist

Out[26]:

[(1, 120, '语文'),
 (2, 55, '数学'),
 (3, 129, '英语'),
 (4, 59, '物理'),
 (5, 89, '化学'),
 (6, 73, '生物'),
 (7, 97, '政治')]

然而有了zip()函数以后,同样的功能实现起来方便很多:

【eg1-26】使用zip函数实现多列表元素一一对应为新列表的子元组:

list(zip(x,y,labels))

Out[27]:

[(1, 120, '语文'),
 (2, 55, '数学'),
 (3, 129, '英语'),
 (4, 59, '物理'),
 (5, 89, '化学'),
 (6, 73, '生物'),
 (7, 97, '政治')]

6. 使用del语句删除列表或从列表按照给定的索引删除元素

pop()方法从原列表删除指定位置的元素并返回被删除的元素值。而del语句广泛用于从内存中将某个对象删除,它与pop()方法有诸多不同:

  • pop()方法有返回值,del()却不存在返回值。
  • python中一切皆对象。每一个对象再他们创建后都将被分配一个内存空间。列表(list)是一种复合数据类型,一个列表本身是一个对象,而列表内的数据亦如此。因此使用del语句不仅能够从内存中删除列表内的某个元素,还能删除整个列表:

【eg1-27】使用del语句删除列表中某个数据:

a = [1, 2, 3, 4, 5, 6, 7]
del(a[2])
a

Out[28]:

[1, 2, 4, 5, 6, 7]

【eg1-28】使用del语句删除整个列表:

a = [1, 2, 3, 4, 5, 6, 7]
del(a)
a
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-252-6553c0a6fea1> in <module>
      1 a = [1, 2, 3, 4, 5, 6, 7]
      2 del(a)
----> 3 a
NameError: name 'a' is not defined

可以看到,a这个变量已经不存在了。因为其作为一个对象已经被del语句从内存中彻底地删除掉了。

有时如果你想使用del删除某个列表所有的数据对象,可以这样写:

【eg1-29】

a = [1, 2, 3, 4, 5, 6, 7]
del a[:]
a

Out[29]: []


7. python列表去重的常用方法

7.1 通过集合(set)对列表去重

在python中列表和集合的区别在于列表中的元素是允许重复的而集合却不行。因此在日常编写代码过程中我们常常使用集合来实现列表中元素的去重:

【eg1-30】对列表中的元素进行去重:

alist = [9,1,1,2,2,1,3,0,5]
set(alist)                  # 由于我们值关心其中的元素是否有重复的就不转列表了

Out[29]: {0, 1, 2, 3, 5, 9}

应用举例:统计列表中所有元素的出现次数

names = ['小明','李华','张三','小明','小明','王五','李四','赵六','王五','张三','李四']
counter = {}
for i in set(names):
    counter[i]=names.count(i)
counter

Out[30]: {‘张三’: 2, ‘王五’: 2, ‘李四’: 2, ‘赵六’: 1, ‘李华’: 1, ‘小明’: 3}

【注】:python中自带了一个集合模块collection提供了获取可迭代对象中每个元素出现次数的方法。

方法3 - 通过强制转化为字典(dict)对列表去重

与方法1思路基本一致,因为在字典数据结构中,键是不能有重复的。

alist = [9,1,1,2,2,1,3,0,5]
list({}.fromkeys(alist).keys())

Out[31]: [9, 1, 2, 3, 0, 5]

7.2 通过列表推导去重

alist = [9,1,1,2,2,1,3,0,5]
a = []
[a.append(i) for i in alist if not i in a]

Out[32]: [9, 1, 2, 3, 0, 5]

8. 列表求交集、并集、差集

8.1 求并交

a = [0,1,4,6,6,5,1]
b = [3,2,6,7,0,9,13,1]
[i for i in a if i in b]

Out[33]: [0, 1, 6, 6, 1]

8.2 求并集

a = [0,1,4,6,6,5,1]
b = [3,2,6,7,0,9,13,1]
list(set(a) | set(b))

Out[34]: [0, 1, 2, 3, 4, 5, 6, 7, 9, 13]

8.3 求差集

[友情提示]:数学上差集指在前一个集合排除后一个集合中存在的元素,且两个集合都是无重复元素的。由于Python列表中是允许存在重复元素的,因此我们定义两个列表的差集是它们对应的集合的差集。

A = [0,1,4,6,6,5,1]
B = [3,2,6,7,0,9,13,1]
setB = list(set(B))
[i for i in set(A) if i not in setB]

Out[34]: [4, 5]

目录
相关文章
|
3天前
|
索引 Python
Python列表
Python列表。
26 8
|
5天前
|
C语言 Python
[oeasy]python054_python有哪些关键字_keyword_list_列表_reserved_words
本文介绍了Python的关键字列表及其使用规则。通过回顾`hello world`示例,解释了Python中的标识符命名规则,并探讨了关键字如`if`、`for`、`in`等不能作为变量名的原因。最后,通过`import keyword`和`print(keyword.kwlist)`展示了Python的所有关键字,并总结了关键字不能用作标识符的规则。
24 9
|
13天前
|
数据挖掘 大数据 数据处理
python--列表list切分(超详细)
通过这些思维导图和分析说明表,您可以更直观地理解Python列表切分的概念、用法和实际应用。希望本文能帮助您更高效地使用Python进行数据处理和分析。
25 14
|
15天前
|
数据挖掘 大数据 数据处理
python--列表list切分(超详细)
通过这些思维导图和分析说明表,您可以更直观地理解Python列表切分的概念、用法和实际应用。希望本文能帮助您更高效地使用Python进行数据处理和分析。
29 10
|
1月前
|
开发者 Docker Python
从零开始:使用Docker容器化你的Python Web应用
从零开始:使用Docker容器化你的Python Web应用
37 1
|
1月前
|
数据处理 开发者 Python
Python中的列表推导式:简洁高效的数据处理
在编程世界中,效率和可读性是代码的两大支柱。Python语言以其独特的简洁性和强大的表达力,为开发者提供了众多优雅的解决方案,其中列表推导式便是一个闪耀的例子。本文将深入探讨列表推导式的使用场景、语法结构及其背后的执行逻辑,带你领略这一特性的魅力所在。
|
1月前
|
开发者 Python
探索Python中的列表推导式:简洁而强大的工具
【10月更文挑战第41天】 在编程的世界中,效率与简洁是永恒的追求。本文将深入探讨Python编程语言中一个独特且强大的特性——列表推导式(List Comprehension)。我们将通过实际代码示例,展示如何利用这一工具简化代码、提升性能,并解决常见编程问题。无论你是初学者还是资深开发者,掌握列表推导式都将使你的Python之旅更加顺畅。
|
1月前
|
Python
探索Python中的列表推导式
【10月更文挑战第38天】本文深入探讨了Python中强大而简洁的编程工具——列表推导式。从基础使用到高级技巧,我们将一步步揭示如何利用这个特性来简化代码、提高效率。你将了解到,列表推导式不仅仅是编码的快捷方式,它还能帮助我们以更加Pythonic的方式思考问题。准备好让你的Python代码变得更加优雅和高效了吗?让我们开始吧!
|
1月前
|
JavaScript 前端开发 算法
python中的列表生成式和生成器
欢迎来到瑞雨溪的博客,这里是一位热爱JavaScript和Vue的大一学生的天地。通过自学前端技术2年半,现正向全栈开发迈进。如果你从我的文章中受益,欢迎关注,我将持续更新高质量内容,你的支持是我前进的动力!🎉🎉🎉
24 0
|
4月前
|
测试技术 索引 Python
Python接口自动化测试框架(基础篇)-- 常用数据类型list&set()
本文介绍了Python中list和set两种数据类型的使用,包括它们的创建、取值、增删改查操作、排序以及内置函数的使用,还探讨了list的比较函数和set的快速去重功能。
38 0