杰瑞科技汇

python切片1012python切片

Python切片 1012:从入门到精通

Python 切片是一种非常强大且优雅的特性,它允许你轻松地获取序列(如列表、元组、字符串)的一部分,而无需编写复杂的循环,掌握切片是 Python 编程的必备技能。

python切片1012python切片-图1
(图片来源网络,侵删)

第一部分:101 切片基础 - 搞懂 [:]

切片的基本语法非常简单,核心是方括号 [] 和冒号 。

sequence[start:stop:step]

让我们来分解这三个参数:

  • sequence: 你想要切片的对象,my_list = [0, 1, 2, 3, 4, 5]
  • start: 起始索引,切片将从这个索引开始,包含这个索引本身,如果省略,默认为 0
  • stop: 结束索引,切片将在这个索引之前结束,不包含这个索引本身,如果省略,默认为序列的长度。
  • step: 步长,表示每次取元素时要“跳过”几个,如果省略,默认为 1

最简单的切片:复制整个序列

当你不提供任何参数时,[:] 会创建一个原序列的浅拷贝

python切片1012python切片-图2
(图片来源网络,侵删)
my_list = [0, 1, 2, 3, 4, 5]
new_list = my_list[:]
print(new_list)        # 输出: [0, 1, 2, 3, 4, 5]
print(new_list is my_list) # 输出: False,证明是两个不同的对象

只提供 stop:从开头到指定位置

my_list = [0, 1, 2, 3, 4, 5]
# 获取索引 0 到 3 (不包含 3) 的元素
slice_result = my_list[:3]
print(slice_result)    # 输出: [0, 1, 2]

只提供 start:从指定位置到结尾

my_list = [0, 1, 2, 3, 4, 5]
# 获取索引 2 到结尾的元素
slice_result = my_list[2:]
print(slice_result)    # 输出: [2, 3, 4, 5]

同时提供 startstop:从指定位置到指定位置

my_list = [0, 1, 2, 3, 4, 5]
# 获取索引 1 到 4 (不包含 4) 的元素
slice_result = my_list[1:4]
print(slice_result)    # 输出: [1, 2, 3]

提供所有三个参数:加入步长

my_list = [0, 1, 2, 3, 4, 5]
# 从索引 1 开始,到索引 5 结束,每隔 2 个取一个
slice_result = my_list[1:5:2]
print(slice_result)    # 输出: [1, 3] (取索引 1,1+2=3,3+2=5,但5不包含)
# 获取所有元素,但每隔一个取一个 (俗称“隔一个取一个”)
slice_result = my_list[::2]
print(slice_result)    # 输出: [0, 2, 4]

第二部分:102 进阶技巧 - 负索引和省略参数

现在我们来看看让切片变得更灵活的两种技巧。

负索引

Python 支持负索引,它从序列的末尾开始计数。-1 是最后一个元素,-2 是倒数第二个,以此类推。

my_list = [0, 1, 2, 3, 4, 5]
# 获取倒数第三个元素到结尾
slice_result = my_list[-3:]
print(slice_result)    # 输出: [3, 4, 5]
# 获取从开头到倒数第三个元素 (不包含)
slice_result = my_list[:-3]
print(slice_result)    # 输出: [0, 1, 2]
# 获取倒数第四个到倒数第二个元素
slice_result = my_list[-4:-1]
print(slice_result)    # 输出: [2, 3, 4]

省略 startstop 与负步长结合

step 为负数时,切片会从后往前取,这时,startstop 的默认值会发生变化:

  • start 的默认值是序列的最后一个元素(索引 -1)。
  • stop 的默认值是序列的开头(索引 -len(sequence)-1,即最前面一个元素的前面)。

技巧:使用 [::-1] 来反转序列

python切片1012python切片-图3
(图片来源网络,侵删)

这是 Python 中最酷、最常用的切片技巧之一!

my_list = [0, 1, 2, 3, 4, 5]
# 反转列表
reversed_list = my_list[::-1]
print(reversed_list)   # 输出: [5, 4, 3, 2, 1, 0]
my_string = "Python"
reversed_string = my_string[::-1]
print(reversed_string) # 输出: "nohtyP"

其他负步长例子:

my_list = [0, 1, 2, 3, 4, 5]
# 从倒数第二个元素开始,到开头结束,步长为 -1 (相当于 my_list[-1::-1])
slice_result = my_list[-2::-1]
print(slice_result)    # 输出: [4, 3, 2, 1, 0, 5] (从4开始,一直往前取)
# 从倒数第二个元素开始,取到倒数第五个元素 (不包含),步长为 -1
slice_result = my_list[-2:-5:-1]
print(slice_result)    # 输出: [4, 3, 2]

第三部分:重要注意事项和边界情况

索引越界怎么办?

Python 切片非常“宽容”,即使你提供的 startstop 超出了序列的范围,它也不会报错,而是会自动调整到有效的边界。

my_list = [0, 1, 2, 3, 4, 5]
# start 超出范围
print(my_list[10:])    # 输出: [] (从第10个开始,但没有,所以返回空列表)
# stop 超出范围
print(my_list[:10])    # 输出: [0, 1, 2, 3, 4, 5] (取到第10个,但列表只有6个,所以取全部)
# start > stop 且 step 为正
print(my_list[5:2])    # 输出: [] (从5开始,要到2结束,但步长是正的,所以无法前进,返回空)

切片是“浅拷贝”

切片操作会创建一个包含原序列部分元素的新序列,对于列表等可变对象,新列表中的元素是对原列表中元素的引用

这意味着,如果元素是不可变的(如数字、字符串、元组),修改新列表不会影响原列表,但如果元素是可变的(如另一个列表),情况就不同了。

# 情况一:元素是不可变的
list_a = [1, 2, 3]
list_b = list_a[:]
list_b[0] = 99
print(f"list_a: {list_a}") # 输出: list_a: [1, 2, 3]
print(f"list_b: {list_b}") # 输出: list_b: [99, 2, 3]
# 情况二:元素是可变的(嵌套列表)
list_c = [[1, 2], [3, 4]]
list_d = list_c[:]
# 修改 list_d 中的第一个元素 (这是一个列表)
list_d[0].append(99) 
print(f"list_c: {list_c}") # 输出: list_c: [[1, 2, 99], [3, 4]]
print(f"list_d: {list_d}") # 输出: list_d: [[1, 2, 99], [3, 4]]
# 因为 list_d[0] 和 list_c[0] 指向的是同一个列表对象,所以修改会相互影响。

分享:
扫描分享到社交APP
上一篇
下一篇