3、操作列表
- for循环
Python根据缩进来判断代码行与前一个代码行的关系。在for循环中,利用缩进表示代码块。for语句末尾的冒号告诉Python,下一行是循环的第一行。
bicycles = ['trek','cannondale','redline','specialized']
for bicycle in bicycles:
print(bicycle)
输出:
trek
cannondale
redline
specialized
在for循环后,没有缩进的代码都只执行一次,不会重复执行。
- range()函数
生成一系列数,左闭右开,可用于for循环或者产生可迭代结构,如列表,调用有以下两种:
range(stop:int), 从0产生一些列整数,到stop的前一个值处停止。
range(start:int, stop:int, step:int), 从start开始,以step为步长,到stop的前一个数停止。如果步长太长,最后一个输出的数也绝不会超过stop的前一个数,如下面代码示例。
numbers = list(range(3)) # range(stop:int)
print(numbers)
enven_numbers = list(range(2,11,2)) #range(start:int, stop:int, step:int)
all_numbers = list(range(1,11,5))
print(enven_numbers)
print(all_numbers)
输出:
[0, 1, 2]
[2, 4, 6, 8, 10]
[1, 6]
- for循环的两种重要用法
- 利用enumerate()同时访问列表下标和值
- 利用range()函数遍历列表的下标
'''
Author: your name
Date: 2021-10-09 09:40:34
LastEditTime: 2021-10-24 20:20:11
LastEditors: Please set LastEditors
Description: In User Settings Eitem
FilePath: /Python/test/test.py
'''
items = [1,3,5]
#同时访问下标和值
for i, v in enumerate(items):
print(i,v)
#访问下标
n = len(items)
for i in range(n):
for j in range(i+1, n): #访问下标i+1到n-1的元素
print(items[j])
输出:
0 1
1 3
2 5
3
5
5
- 对数字列表执行简单的统计计算
- min(iterable) : 取最小值
- max (iterable) :取最大值
- sum (iterable) : 取总和
digits = [1,2,3,4,5,6,7,8,9,0]
mi = min(digits)
ma = max(digits)
su = sum(digits)
print(f"mi = {mi}, ma = {ma}, su = {su}")
输出:
mi = 0, ma = 9, su = 45
- 列表解析
有时候我们需要创建复杂列表,如下面例子中的平方数列表,利用for循环有时显得不够简洁,列表解析将for循环和创建新元素的代码合并成一行,并自动附加新元素。
#例一
squares = [value**2 for value in range(1,11)]
print(squares)
#例二
fruits = ['apple', 'banana', 'watermelon']
upper_fruits = [fruit.title() for fruit in fruits] #后半部分和for语句的开头完全相同
print(upper_fruits)
输出:
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
['Apple', 'Banana', 'Watermelon']
- 使用列表的一部分——切片
要创建切片,可指定要使用的第一个元素和最后一个元素的索引。两个索引之间用冒号隔开。与函数range()一样,Python在到达第二个索引之前的元素后停止。由于是左闭右开,用第二个索引值减去第一个索引值,得到的结果就是这个切片包含的元素数量。
item = list(range(0,10,1))
print(item)
cut_item = item[1:6] #取索引为1处(即第二个元素)到索引为5处(左闭右开)元素
print(cut_item)
输出:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5]
如果没有指定第一个索引,Python将自动从列表开头开始。如果没有指定第二个索引,切片将终止于列表末尾。在给末尾元素切片时,可使用负数索引。
可以在两个索引之后添加第三个参数作为步长,它可以告诉Python在指定范围内每隔多少个元素提取一个。
item = list(range(0,10,1))
print(item)
head_cut = item[:3] #不设置第一个索引
print(head_cut,"-------------------item[:3]")
tail_cut = item[4:] #不设置第二个索引
print(tail_cut,"--------------------item[4:]")
tail_cut2 = item[-3:] #使用负数索引
print(tail_cut2,"--------------------item[-3:]")
step_cut = item[1:8:2] #设置切片步长
no_step_cut = item[1:8] #不设置切片步长
print(no_step_cut,"-------------------item[1:8]")
print(step_cut,"---------------------item[1:8:2]")
输出:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2] -------------------item[:3]
[4, 5, 6, 7, 8, 9] --------------------item[4:]
[7, 8, 9] --------------------item[-3:]
[1, 2, 3, 4, 5, 6, 7] -------------------item[1:8]
[1, 3, 5, 7] ---------------------item[1:8:2]
遍历切片——如果要遍历切片中的部分元素,可以在for循环中使用切片。
item = list(range(0,10,1))
print(item)
for i in item[:4]: #计算前四个数的平方根
print(i**2)
输出:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
0
1
4
9
- 列表的多层切片
列表的切片是可以嵌套的,理论情况下,只要上一层的切片不为空,就可以一直嵌套。这多层切片有一种很实用的应用是反转数组。对一个列表nums[::-1]也就是将步长设为-1,可以实现对列表某一部分的反转。如下例,利用多层切片实现对列表前四个数的反转:
nums = [1,2,3,4,5,6,7]
nums[0:4] = nums[0:4][::-1]
print(result)
输出:
[4, 3, 2, 1, 5, 6, 7]
- 复制列表
如果要复制列表,可创建一个包含整个列表的切片,方法是同时省略起始索引和终止索引( [:] )。这样Python就创建了一个起始于第一个元素、终止于最后一个元素的切片,即整个列表的副本。
值得一提的是,如果我们将一个列表直接赋值给另一个列表,两个列表会指向同一个内存空间,当改变其中一个的值时,另一个列表的值也会被改变。如果像前面所述利用切片创建复制,得到的新列表会指向另外的空间,对任何一个列表的操作不会出现在另一个列表中。
item = list(range(0,10,1))
print(item)
print("切片复制测试:")
copy_item = item[:]
print(copy_item)
copy_item.append(666) #只有copy_item会在末尾插入666
print(item)
print(copy_item)
print("直接赋值测试:")
assignment_item = item
print(assignment_item)
assignment_item.append(666) #两个列表会同时在末尾插入666
print(item)
print(assignment_item)
输出:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
切片复制测试:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 666]
直接赋值测试:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 666]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 666]
- 一个有趣的讨论:切片是不是列表一部分的复制
切片是不是列表一部分的复制,这一问题很好判断,只需要看我们在对切片进行操作的时候,完整的列表是否会相应的变化即可。看如下例子:
a_nums = [1,2,3,4,5,6,7]
a = a_nums
a[0:4] = a_nums[0:4][::-1]
print("使用浅复制的测试:")
print(a)
print(a_nums)
#将切片赋值给一个变量
b_nums = [1,2,3,4,5,6,7]
b = b_nums[0:4]
b = b[::-1]
print("将切片复制的测试:")
print(b)
print(b_nums)
c_nums = [1,2,3,4,5,6,7]
c_nums[0:4] = c_nums[0:4][::-1]
print("直接使用切片的测试:")
print(c_nums
输出:
使用浅复制的测试:
[4, 3, 2, 1, 5, 6, 7]
[4, 3, 2, 1, 5, 6, 7]
将切片复制的测试:
[4, 3, 2, 1]
[1, 2, 3, 4, 5, 6, 7]
直接使用切片的测试:
[4, 3, 2, 1, 5, 6, 7]
第一部分,我们使用浅复制将a_nums赋值给a,然后对a的切片进行操作,可以看到同时操作了a_nums。第二部分,我们将b_nums的切片赋值给一个变量,然后对变量进行操作,可以发现,变量的内容翻转了,但是b_nums的内容并没有变化,可见此处变量的值时b_nums切片的复制。第三部分,我们直接对c_nums的切片进行多层切片操作,可以发现nums的内容改变了。
由此得出结论:
- 切片本身不是一个复制,可以视为对列表自身一部分的截取,在切片上的操作等同于对列表本身的操作。
- 当我们将列表的一个切片赋值给一个变量时,变量就得到了一个关于切片的副本,对变量的操作与列表本身无关。
- 使用浅复制直接将列表赋值给一个变量时,对该变量的任何操作都等同于直接对列表的操作。
- 元组
列表——可修改,适合用于存储在程序运行期间可能变化的数据集。
元组——不可修改,即元组的值不可变,用于存储不希望被修改的元素。
元组看起来很像列表,但使用圆括号而非中括号来标识。定义元组之后,就可使用索引来访问元素,就像访问列表元素一样。
严格的说,元组是由逗号标识的,圆括号知识让元组看起来更整洁、清晰。如果要定义只包含一个元素的元组,必须在这个元祖后面加上逗号。创建只包含一个元素的元组通常没有意义,但自动生成的元组有可能只有一个元素。
元组的定义:
item = tuple(range(1,10,2)) #可以使用range函数创建元组
print(item)
item2 = (1,2) #可以直接定义元组
print(item2)
item3 = (3,) #创建只有一个元素的元组
print(item3)
输出:
(1, 3, 5, 7, 9)
(1, 2)
(3,)
可以像遍历列表一样使用for循环遍历元组
item = tuple(range(1,10,2))
print(item)
for i in item:
print(i**2)
输出:
(1, 3, 5, 7, 9)
1
9
25
49
81
虽然不能修改远足的额元素,但是可以给存储元组的变量复制,即不能对元组的元素进行修改,但是可以重新定义整个元组。
item = (1,2)
print(item)
item = (9,10)
print(item)
输出:
(1, 2)
(9, 10)
试图修改元组元素时,会报错:
item = (1,2)
print(item)
item[0] = 6
错误提示:
Traceback (most recent call last):
File "/Users/liheng/Documents/CODES/Python/test.py", line 4, in <module>
item[0] = 6
TypeError: 'tuple' object does not support item assignment
总而言之,元组是比列表更简单的数据结构,如果需要存储的一组值在程序的整个生命周期内都不变,就可以使用元组。
- 获取列表特定元素下标
- 方法index(value, start, end)
在范围(start, end)内查找value的下标,如果有多个重复value,会返回第一个值。 - 方法enumerate(sequence, start)
对于sequence,从下标start开始,返回(index, value)这样的元组组成的列表。下面for循环中的用法是最常见的。
- 方法index(value, start, end)
items = [1,3,5,7,9,3,1]
location_1 = items.index(1,2,) #end出不添加值则是到列表末尾
print(location_1)
location_1 = items.index(1)
print(location_1)
location_2 = list(enumerate(items))
print(location_2)
for i, v in enumerate(items):
print(i,v)
输出:
6
0
[(0, 1), (1, 3), (2, 5), (3, 7), (4, 9), (5, 3), (6, 1)]
0 1
1 3
2 5
3 7
4 9
5 3
6 1