列表的办法

列表类型的变量拥有很多办法能够协助咱们操作一个列表,假定咱们有名为foos的列表,列表有名为bar的办法,那么运用列表办法的语法是:foos.bar(),这是一种经过目标引证调用目标办法的语法。后边咱们讲面向目标编程的时候,还会对这种语法进行详细的讲解,这种语法也称为给目标发消息。

增加和删去元素

列表是一种可变容器,可变容器指的是咱们能够向容器中增加元素、能够从容器移除元素,也能够修正现有容器中的元素。咱们能够运用列表的append办法向列表中追加元素,运用insert办法向列表中插入元素。追加指的是将元素增加到列表的末尾,而插入则是在指定的方位增加新元素,咱们能够看看下面的代码。

languages = ['Python', 'Java', 'C++']
languages.append('JavaScript')
print(languages)  # ['Python', 'Java', 'C++', 'JavaScript']
languages.insert(1, 'SQL')
print(languages)  # ['Python', 'SQL', 'Java', 'C++', 'JavaScript']

咱们能够用列表的remove办法从列表中删去指定元素,需求留意的是,假如要删去的元素并不在列表中,会引发ValueError错误导致程序溃散,所以主张咱们在删去元素时,先用之前讲过的成员运算做一个判别。咱们还能够运用pop办法从列表中删去元素,pop办法默认删去列表中的终究一个元素,当然也能够给一个方位,删去指定方位的元素。在运用pop办法删去元素时,假如索引的值超出了规模,会引发IndexError反常,导致程序溃散。除此之外,列表还有一个clear办法,能够清空列表中的元素,代码如下所示。

languages = ['Python', 'SQL', 'Java', 'C++', 'JavaScript']
if 'Java' in languages:
    languages.remove('Java')
if 'Swift' in languages:
    languages.remove('Swift')
print(languages)  # ['Python', 'SQL', C++', 'JavaScript']
languages.pop()
temp = languages.pop(1)
print(temp)       # SQL
languages.append(temp)
print(languages)  # ['Python', C++', 'SQL']
languages.clear()
print(languages)  # []

阐明pop办法删去元素时会得到被删去的元素,上面的代码中,咱们将pop办法删去的元素赋值给了名为temp的变量。当然假如你乐意,还能够把这个元素再次加入到列表中,正如上面的代码languages.append(temp)所做的那样。

这里还有一个小问题,例如languages列表中有多个'Python',那么咱们用languages.remove('Python')是删去所有的'Python',仍是删去第一个'Python',咱们能够先猜一猜,然后再自己着手测验一下。

从列表中删去元素其实还有一种办法,便是运用 Python 中的del关键字后边跟要删去的元素,这种做法跟运用pop办法指定索引删去元素没有实质性的区别,但后者会返回删去的元素,前者在功能上略优,由于del对应的底层字节码指令是DELETE_SUBSCR,而pop对应的底层字节码指令是CALL_METHODPOP_TOP,假如不了解就不必管它了。

items = ['Python', 'Java', 'C++']
del items[1]
print(items)  # ['Python', 'C++']

元素方位和频次

列表的index办法能够查找某个元素在列表中的索引方位,假如找不到指定的元素,index办法会引发ValueError错误;列表的count办法能够计算一个元素在列表中呈现的次数,代码如下所示。

items = ['Python', 'Java', 'Java', 'C++', 'Kotlin', 'Python']
print(items.index('Python'))     # 0
# 从索引方位1开始查找'Python'
print(items.index('Python', 1))  # 5
print(items.count('Python'))     # 2
print(items.count('Kotlin'))     # 1
print(items.count('Swfit'))      # 0
# 从索引方位3开始查找'Java'
print(items.index('Java', 3))    # ValueError: 'Java' is not in list

元素排序和回转

列表的sort操作能够完成列表元素的排序,而reverse操作能够完成元素的回转,代码如下所示。

items = ['Python', 'Java', 'C++', 'Kotlin', 'Swift']
items.sort()
print(items)  # ['C++', 'Java', 'Kotlin', 'Python', 'Swift']
items.reverse()
print(items)  # ['Swift', 'Python', 'Kotlin', 'Java', 'C++']

列表生成式

在 Python 中,列表还能够经过一种特殊的字面量语法来创立,这种语法叫做生成式。下面,咱们经过比如来阐明运用列表生成式创立列表到底有什么好处。

场景一:创立一个取值规模在199且能被3或者5整除的数字构成的列表。

items = []
for i in range(1, 100):
    if i % 3 == 0 or i % 5 == 0:
        items.append(i)
print(items)

运用列表生成式做相同的工作,代码如下所示。

items = [i for i in range(1, 100) if i % 3 == 0 or i % 5 == 0]
print(items)

场景二:有一个整数列表nums1,创立一个新的列表nums2nums2中的元素是nums1中对应元素的平方。

nums1 = [35, 12, 97, 64, 55]
nums2 = []
for num in nums1:
    nums2.append(num ** 2)
print(nums2)

运用列表生成式做相同的工作,代码如下所示。

nums1 = [35, 12, 97, 64, 55]
nums2 = [num ** 2 for num in nums1]
print(nums2)

场景三: 有一个整数列表nums1,创立一个新的列表nums2,将nums1中大于50的元素放到nums2中。

nums1 = [35, 12, 97, 64, 55]
nums2 = []
for num in nums1:
    if num > 50:
        nums2.append(num)
print(nums2)

运用列表生成式做相同的工作,代码如下所示。

nums1 = [35, 12, 97, 64, 55]
nums2 = [num for num in nums1 if num > 50]
print(nums2)

运用列表生成式创立列表不仅代码简略优雅,而且功能上也优于运用for-in循环和append办法向空列表中追加元素的办法。为什么说生成式有更好的功能呢,那是由于 Python 解释器的字节码指令中有专门针对生成式的指令(LIST_APPEND指令);而for循环是经过办法调用(LOAD_METHODCALL_METHOD指令)的办法为列表增加元素,办法调用自身便是一个相对比较耗时的操作。对这一点不了解也没有联系,记住“强烈主张用生成式语法来创立列表”这个结论就能够了。

嵌套列表

Python 言语没有限定列表中的元素必须是相同的数据类型,也便是说一个列表中的元素能够恣意的数据类型,当然也包括列表自身。假如列表中的元素也是列表,那么咱们能够称之为嵌套的列表。嵌套的列表能够用来表明表格或数学上的矩阵,例如:咱们想保存5个学生3门课程的成果,能够用如下所示的列表。

scores = [[95, 83, 92], [80, 75, 82], [92, 97, 90], [80, 78, 69], [65, 66, 89]]
print(scores[0])
print(scores[0][1])

关于上面的嵌套列表,每个元素适当于便是一个学生3门课程的成果,例如[95, 83, 92],而这个列表中的83代表了这个学生某一门课的成果,假如想拜访这个值,能够运用两次索引运算scores[0][1],其间scores[0]能够得到[95, 83, 92]这个列表,再次运用索引运算[1]就能够获得该列表中的第二个元素。

假如想经过键盘输入的办法来录入5个学生3门课程的成果并保存在列表中,能够运用如下所示的代码。

scores = []
for _ in range(5):
    temp = []
    for _ in range(3):
        score = int(input('请输入: '))
        temp.append(score)
    scores.append(temp)
print(scores)

假如想经过发生随机数的办法来生成5个学生3门课程的成果并保存在列表中,咱们能够运用列表生成式,代码如下所示。

import random
scores = [[random.randrange(60, 101) for _ in range(3)] for _ in range(5)]
print(scores)

阐明:上面的代码[random.randrange(60, 101) for _ in range(3)] 能够发生由3个随机整数构成的列表,咱们把这段代码又放在了另一个列表生成式中作为列表的元素,这样的元素一共生成5个,终究得到了一个嵌套列表。

列表使用举例

下面咱们经过一个双色球随机选号的比如为咱们讲解列表的使用。双色球是由中国福利彩票发行管理中心发售的乐透型彩票,每注投注号码由6个赤色球和1个蓝色球组成。赤色球号码从133中挑选,蓝色球号码从116中挑选。每注需求挑选6个赤色球号码和1个蓝色球号码,如下所示。

从零开始学Python第09课:常用数据结构之列表-2

提示:知乎上有一段对国内各种办法的彩票本质的论说适当精彩,这里分享给咱们:“虚构一个坐收渔利的人,去忽悠一群想坐收渔利的人,终究养活一批真正坐收渔利的人”。珍爱生命,远离(任何办法的)赌博!

下面,咱们经过 Python 程序来生成一组随机号码。

"""
双色球随机选号程序
Author: 骆昊
Version: 1.0
"""
import random
red_balls = list(range(1, 34))
selected_balls = []
# 增加6个赤色球到选中列表
for _ in range(6):
    # 生成随机整数代表选中的赤色球的索引方位
    index = random.randrange(len(red_balls))
    # 将选中的球从赤色球列表中移除并增加到选中列表
    selected_balls.append(red_balls.pop(index))
# 对选中的赤色球排序
selected_balls.sort()
# 输出选中的赤色球
for ball in selected_balls:
    print(f'\033[031m{ball:0>2d}\033[0m', end=' ')
# 随机挑选1个蓝色球
blue_ball = random.randrange(1, 17)
# 输出选中的蓝色球
print(f'\033[034m{blue_ball:0>2d}\033[0m')

阐明:上面代码中print(f'\033[0m...\033[0m')是为了控制输出内容的色彩,赤色球输出成赤色,蓝色球输出成蓝色。其间省掉号代表咱们要输出的内容,\033[0m是一个控制码,表明封闭所有属性,也便是说之前的控制码将会失效,你也能够将其简略的了解为一个定界符,m前面的0表明控制台的显示办法为默认值,0能够省掉,1表明高亮5表明闪耀,7表明反显等。在0m的中心,咱们能够写上代表色彩的数字,比如30代表黑色,31代表赤色,32代表绿色,33代表黄色,34代表蓝色等。

咱们还能够利用random模块供给的samplechoice函数来简化上面的代码,前者能够完成无放回随机抽样,后者能够完成随机抽取一个元素,修正后的代码如下所示。

"""
双色球随机选号程序
Author: 骆昊
Version: 1.1
"""
import random
red_balls = [i for i in range(1, 34)]
blue_balls = [i for i in range(1, 17)]
# 从赤色球列表中随机抽出6个赤色球(无放回抽样)
selected_balls = random.sample(red_balls, 6)
# 对选中的赤色球排序
selected_balls.sort()
# 输出选中的赤色球
for ball in selected_balls:
    print(f'\033[031m{ball:0>2d}\033[0m', end=' ')
# 从蓝色球列表中随机抽出1个蓝色球
blue_ball = random.choice(blue_balls)
# 输出选中的蓝色球
print(f'\033[034m{blue_ball:0>2d}\033[0m')

假如要完成随机生成N注号码,咱们只需求将上面的代码放到一个N次的循环中,如下所示。

"""
双色球随机选号程序
Author: 骆昊
Version: 1.2
"""
import random
n = int(input('生成几注号码: '))
red_balls = [i for i in range(1, 34)]
blue_balls = [i for i in range(1, 17)]
for _ in range(n):
    # 从赤色球列表中随机抽出6个赤色球(无放回抽样)
    selected_balls = random.sample(red_balls, 6)
    # 对选中的赤色球排序
    selected_balls.sort()
    # 输出选中的赤色球
    for ball in selected_balls:
        print(f'\033[031m{ball:0>2d}\033[0m', end=' ')
    # 从蓝色球列表中随机抽出1个蓝色球
    blue_ball = random.choice(blue_balls)
    # 输出选中的蓝色球
    print(f'\033[034m{blue_ball:0>2d}\033[0m')

咱们在 PyCharm 中运转上面的代码,输入5,运转效果如下图所示。

从零开始学Python第09课:常用数据结构之列表-2

总结

Python 中的列表底层是一个能够动态扩容的数组,列表元素在计算机内存中是连续存储的,所以能够完成随机拜访(经过一个有效的索引获取对应的元素且操作时刻与列表元素个数无关)。咱们能够暂时不去触碰这些底层的存储细节,也不需求咱们了解列表每个办法的渐近时刻复杂度(执行办法消耗的时刻跟列表元素个数之间的联系),咱们先学会用列表解决工作中的问题,我想这一点更为重要。