Python学习笔记(3) —— 列表操作和循环

本文详细介绍了Python中的列表操作,包括for循环遍历、while循环、数值列表的创建、列表解析、简单统计计算、切片、复制以及元组的使用。通过实例解析了for与while在循环中的应用,并探讨了continue和break的作用。同时,文章讨论了列表的切片特性以及如何通过range和列表解析创建复杂列表。最后,提到了列表的浅拷贝问题,并引出了元组作为不可变数据类型的特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

for循环与列表的遍历

先写一个简单的列表循环遍历代码,这样说明比较直观与方便些:

names = [ 'ZhangSan', 'LiSi', 'WangWu' ]
for name in names:
    print(name)

这段代码结果显示:
ZhangSan
LiSi
WangWu

这段代码就是一个简单的链表循环遍历,下面我逐一说明下:

第一行定义了 一个名为names的列表,里面有三个元素分别为 ‘ZhangSan’, ‘LiSi’, ‘WangWu’。
第二行是一个for循环用来遍历列表names里的元素,for循环的基本格式是:

for  变量  in  可迭代的集合 : 
    循环语句1
    循环语句2
    .
    .
    .
    循环语句n

for循环的行为是在每次循环时从 可迭代的集合 中取出一个元素赋值给 变量 ,然后下面的循环语句中就可以使用这个变量,最后直到集合中的每一个元素都被遍历了一次之后 循环结束。
第三行就是将变量name(每次循环遍历时从names列表中取出一个元素赋值得来)打印出来。

这里需要注意的是一下几点:

  1. for循环后的冒号不要忘了,这是告诉编译器后面有语句而且是和从属于这一行的。(问:那就写个for语句,后面什么都不跟行不行? 答:不行,如果想什么都不做那也要跟一个pass语句,否则编译不通过)
  2. for后面的循环语句都要统一缩进(4个空格或一个tab),python对于格式的缩进要就极其严格,多了少了都不行,因为编译器需要用缩进来判断这个语句到底是属于哪一个代码块。一旦缩进不对要么编译器解析你的代码时报错,要么碰巧编译过了却和你想要的运行顺序不一样。
  3. 如果后面的代码不是循环体的一部分,那么只要去掉一个tab缩进就好了。在python中你可以用缩进来一眼看出代码的层次结构,这也是python令人喜欢的地方之一,代码读起来结构清晰明了。

while循环

既然写到了for循环那么也把while循环介绍下,这样能对比着看一下,我想介绍完了也就明白为什么列表的循环一般都用for而不是while。
while语句的基本结构为:

while 逻辑判断表达式:
    循环语句1
    循环语句2
    .
    .
    .
    循环语句n

while循环的行为是只要逻辑判断表达式的结果为真,则执行循环语句,直至逻辑判断表达式的结果为假时退出。
那么同样是上面的列表,如果用while遍历该怎么写呢?以下是代码:

names = [ 'ZhangSan', 'LiSi', 'WangWu' ]
names_len = len(names)
index = 0
while index < names_len:
    print(names[index])
    index += 1

看到了吧,for用3行解决的事儿,while需要6行。那么为什么要有while循环呢?那是因为某些情况下while循环比for用起来能更方便的描述现实情况。比如和用户交互,比如一个游戏程序什么时候结束。一般来说执行循环时有明确循环次数的用for循环,而循环次数是未知时则用while循环。

说到循环还有两个关键词不得不说一下,一个是continue,一个是break,这两个关键词经常能在循环中看到。

  • continue: 当程序在循环中执行到continue时,程序立刻从循环的头部开始下一次循环的执行(如此一来continue语句下面的循环语句自然是执行不到了)
  • break:当程序在循环中执行到break时,程序跳出循环(后面的循环不再执行)接着执行外部语句

continue例子:

names = [ 'ZhangSan', 'LiSi', 'WangWu' ]
names_len = len(names)
index = 0
while index < names_len:
    print(names[index])
    index += 1
    continue
    print(names[index])

这段代码的执行结果和上面的一样,因为程序执行到continue后返回循环起始处接着执行下一次循环,后面的print语句根本执行不到

break例子:

names = [ 'ZhangSan', 'LiSi', 'WangWu' ]
names_len = len(names)
index = 0
while index < names_len:
    print(names[index])
    index += 1
    break
    print(names[index])

这段代码的执行结果只有一行 ZhangSan,因为程序执行到break后直接跳出循环,后面的循环以及循环体代码都被略过了。有不少人为死循环的退出就是使用break语句跳出死循环的。

在上面的while循环中我提到了逻辑表达式,这其中经常会用到两个关键词,一个是and 一个是 or(也就是C系列语言中的&& 和 || ):

  • and:表示并列关系,当左右两边表达式都为真时结果为真,其他情况结果都为假
  • or :表示或者关系,当左右两边表达式都为假时结果为假,其他情况结果都为真

数值列表的创建

有的时候我们需要一个由数值组成的列表,这些数值量大又有一定的规律,有什么办法能帮我们一下子创建出这样的列表吗?
这里就用到了函数range()。
例子:

for num in range(1,5):
    print(num)

结果输出1,2,3,4.
可以发现range函数生成的列表是包含开始数字,不包括结尾数字的。
range函数还可以加上第三个参数来指定步长,如:

for num in range(1,52):
    print(num)

结果输出1,3,
如果发现有一个函数不知道它怎么用可以使用help函数,如:help(range)

列表解析

如果我要的一个数字列表他不是个等差数列怎么办?range函数只能生成等差数列的列表啊。
也是有办法的,这时候就用到列表解析了。
举个例子,如果要生成1到6的立方数列表,那么可以这么写:

nums = [num**3 for num in range(1,7)]
print(nums)

上面代码可以l理解为:

nums = []
for num in range(1,7):
    nums.append(num**3)
print(nums)

再复杂的列表解析都可以这么理解和转换:
比如:

nums = [x*y*z for x in range(1,10,2) for y in range(4,12,3) for z in range(3,8,4)]
print(nums)

等同于

nums = []
for x in range(1,10,2):
    for y in range(4,12,3):
        for z in range(3,8,4):
            nums.append(x*y*z)
print(nums)

还没说到if语句就不往里面加了,如果有if语句那也是照样子展开意思就一目了然了(不要关注里面的数字,数字是我随便选的,关注如何展开就好)

数字列表的简单统计计算

  • min:返回列表中的最小值
  • max:返回列表中的最大值
  • sum:返回列表中数字的和

    例子:

nums = range(1,101)
print(min(nums))
print(max(nums))
print(sum(nums))

结果为:
1
100
5050

列表切片

有的时候我们只想使用列表的一部分那怎么办?
这时候列表的切片功能就能帮上忙了。
例子:

nums = [1,2,3,4,5,6]
nums_slice = nums[0:3]
print(nums)
print(nums_slice)

代码的第二行就是切片操作了,将nums列表从第0号元素到第3号元素(不包括下标为3的元素)进行切片操作,然后赋值给nums_slice。
从这段代码中能看出2个问题:

  1. [起始下标 : 结尾下标] 的切片操作也是包含前面的数字不包含结尾的数字的(python绝大多数表示一个范围的操作都这样)
  2. 切片操作不会影响原来的列表

切片操作能正着切也能反着切:

nums = [1,2,3,4,5,6]
nums_slice = nums[-1:-3:-1]
print(nums_slice)

结果输出
[6,5]
你也许看出来了,这切片操作的3个参数和range函数很像,都是起始,结束,步长。代码中起始下标-1是倒数第一个数,-3是倒数第三个数,步长-1,那么根据切片包含前不包含后的特点结果就是6(下标-1的数)和5(下标-2的数)了。

列表的复制

列表复制也是常常会用到的一个需求,那么列表该如何复制呢?
先看看这样行不行:

nums_1 = [1,2,3]
nums_2 = [1,2,3]
nums_3 = nums_1
print(nums_1)
print(nums_2)
print(nums_3)
nums_1[0] = 6
print(nums_1)
print(nums_2)
print(nums_3)
print(id(nums_1))
print(id(nums_2))
print(id(nums_3))

打印结果为:
[1, 2, 3]
[1, 2, 3]
[1, 2, 3]
[6, 2, 3]
[1, 2, 3]
[6, 2, 3]
140332352455496
140332352583432
140332352455496

这段代码说明了几个问题:

  1. 直接用列表名赋值给另一个变量这不是真正的复制列表,只是把地址给了它,导致两个不同名字的变量指向同一个地址,结果自然是改其中一个另一个看起来也改了。
  2. 指向相同内存地址的变量具有相同的id(id这个函数可以获得一个变量的唯一身份编码),我们可以用id这个函数来识别变量是否指向同一个地址
  3. 用同样的数组元素复制给变量,不会导致两个数组指向同一地址
    (这有点像C里面的指针和地址概念的感觉)

那我们该如何复制呢,总不能每次都手动输入一次吧,数量大了怎么办?这里有两个方法可供选择:

nums_1 = [1,2,3]
nums_2 = nums_1[:] #这种切片中什么都不写的方式 表示切整个列表
nums_3 = nums_1.copy()
print(id(nums_1))
print(id(nums_2))
print(id(nums_3))

输出显示:
140332352585672
140332353006536
140332352545096

id打印结果表明用切片和copy()函数复制列表是可以达成要求的。
需要注意的是这两种方式都是浅拷贝,如果遇到以下这种列表里包含列表的情况就抓瞎了:

nums_1 = [1,2,3,[4,5,6]]
nums_2 = nums_1[:]
nums_3 = nums_1.copy()
nums_1[1]= 9
nums_1[3][0] = 10
print(nums_1)
print(nums_2)
print(nums_3)
print(id(nums_1))
print(id(nums_2))
print(id(nums_3))

显示输出:
[1, 9, 3, [10, 5, 6]]
[1, 2, 3, [10, 5, 6]]
[1, 2, 3, [10, 5, 6]]
140332352939912
140332353033928
140332352517512

从id上能看出这3个变量确实是3个不同的变量,没有指向同一个地址的情况出现,但nums_1列表中的列表[4,5,6]被改了第一个元素,另外两个变量看起来也被改了。这里面涉及到深拷贝的问题,后面再说。

元组

元组的定义方式为:
变量名 = ( 元素1,元素2,…,元素n )
元组的绝大多数操作和列表一致,唯一要注意的是元组不可修改
例子:

nums = (1,2,3,4,5)
print(nums)
nums[0] = 0  #出错 

注意:

nums = (1,2,3,4,5)
print(nums)
nums = (1,2,3)
print(nums)

这不叫修改元组,这是给nums赋值了一个新的元组,所以没问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值