《流畅的Python》学习笔记-第二章 元组与切片(四)

目录

1.什么是元组

2.元组拆包

3.嵌套元组的拆包

4.什么是切片

5.切片操作左闭右开的优点

6.切片练习题

1.判断是否是回文

2.将1d2c3b4a转换成abcd


1.什么是元组

元组(Tuple)是 Python 中的一种基本数据结构,它是一个有序的、不可变的序列。元组中的元素可以是任意类型,可以是数字、字符串、列表等。元组可以用来存储多个值,比如多维数据或者一组记录。

要创建一个元组,可以将一系列值用逗号 , 分隔,并用圆括号 () 包围起来。它与列表非常相似,但列表是可变的(可以修改内容),而元组是不可变的(一旦创建无法修改)。

下面是一个元组的简单例子:

my_tuple = (1, "Python", 3.14)

这个元组包含三个元素:一个整数 1,一个字符串 "Python",以及一个浮点数 3.14

要访问元组中的元素,可以使用类似于列表的索引操作。例如:

first_element = my_tuple[0]  # 结果是整数 1

因为元组是不可变的,所以我们不能修改元组中的元素或给其添加/删除元素。这也是元组与列表最主要的区别之一。

my_tuple[0] = 2  # 这会导致 TypeError,因为元组不支持修改操作

元组有很多用途,例如在函数中返回多个值,作为字典的键(因为字典要求键必须是不可变的),或者存储一些不应该被修改的数据。

2.元组拆包

元组拆包(Tuple Unpacking)是 Python 中的一种用法,它允许我们将元组中的元素分解并分配给多个变量。这在处理元组数据的过程中可以让代码更简洁易读。元组拆包的一个好处是,可以不使用临时变量就交换两个变量的值。

以下是一些元组拆包的例子:

基本的元组拆包:

my_tuple = (1, 2, 3)
a, b, c = my_tuple

print(a)  # 输出结果:1
print(b)  # 输出结果:2
print(c)  # 输出结果:3

注意,变量的数量必须与元组中的元素数量相等,否则会触发 ValueError。

使用星号 * 进行部分拆包:

Python 还允许我们使用星号 * 语法对元组进行部分拆包,这在处理不定长元组时非常有用。

my_tuple = (1, 2, 3, 4, 5)
a, *b, c = my_tuple

print(a)  # 输出结果:1
print(b)  # 输出结果:[2, 3, 4]
print(c)  # 输出结果:5

在这个例子中,ac 分别被赋予了元组的第一个和最后一个元素,而 b 是包含其他元素的列表。

拆包时交换变量值:

元组拆包还可以用于交换两个变量的值,而不需要借助临时变量。

a = 1
b = 2
a, b = b, a

print(a)  # 输出结果:2
print(b)  # 输出结果:1

元组拆包是一种非常实用的技巧,可以帮助我们编写更简洁、更易读的代码。

3.嵌套元组的拆包

嵌套元组拆包是指将元组内包含的子元组拆分并分配给多个变量的过程。这种方法在处理具有嵌套结构的数据时非常有用。拆包嵌套元组时,需要确保变量结构与元组结构匹配。让我们看一些嵌套元组拆包的例子。

基本的嵌套元组拆包:

nested_tuple = (1, (2, 3), 4)
a, (b, c), d = nested_tuple

print(a)  # 输出结果:1
print(b)  # 输出结果:2
print(c)  # 输出结果:3
print(d)  # 输出结果:4

这里,nested_tuple 包含一个子元组 (2, 3)。拆包时,我们需要使用括号将 bc 包裹起来以匹配子元组的结构。最后,我们得到了正确地将元组内的每个值分配给对应变量的结果。

嵌套元组与基本拆包结合:

nested_tuple = (1, (2, 3), (4, 5, 6))
a, (b, c), (d, *e) = nested_tuple

print(a)  # 输出结果:1
print(b)  # 输出结果:2
print(c)  # 输出结果:3
print(d)  # 输出结果:4
print(e)  # 输出结果:[5, 6]

在这个例子中,我们结合了基本拆包和嵌套拆包。我们使用括号将 bc 包裹起来,与第二个子元组的结构保持一致。然后,我们使用带星号的拆包语法 *e 拆解第三个子元组的余下部分。最后,我们正确地将嵌套元组内的每个值分配给对应变量。

嵌套元组拆包可以帮助我们更直观地处理复杂的元组结构,同时保持代码的简洁。

切片(slicing)是 Python 中一种从序列类型(如字符串、列表、元组等)中获取子序列的操作。切片操作使用冒号 : 分隔的下标来表示子序列的起始和终止位置。注意,Python 中的下标是从 0 开始的,并且切片操作是左闭右开的,即包含起始位置,但不包含终止位置。

4.什么是切片

以下是一些对不同序列类型进行切片操作的例子:

对字符串进行切片:

text = "Hello, World!"
sliced_text = text[0:5]

print(sliced_text)  # 输出结果:"Hello"

这个例子中,我们从字符串 text 中取出前 5 个字符(下标 04,不包含下标 5)。

对列表进行切片:

my_list = [1, 2, 3, 4, 5]
sliced_list = my_list[1:4]

print(sliced_list)  # 输出结果:[2, 3, 4]

在这个例子中,我们从列表 my_list 中取出第二个到第四个元素(下标 13)。

对元组进行切片:

my_tuple = (1, 2, 3, 4, 5)
sliced_tuple = my_tuple[2:]

print(sliced_tuple)  # 输出结果:(3, 4, 5)

在这个例子中,我们从元组 my_tuple 中取出第三个元素(下标 2)开始到末尾的所有元素。注意,当只提供一个冒号和终止位置时,切片操作会从序列的开头开始。

使用切片操作时,还可以指定步长,例如:

my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
sliced_list = my_list[1:7:2]

print(sliced_list)  # 输出结果:[2, 4, 6]

在这个例子中,我们从列表 my_list 的下标 1 到下标 6,以步长为 2 的方式获取元素。输出结果是一个新列表 [2, 4, 6]

切片操作是处理序列类型数据时非常实用的功能,而且编写起来非常简洁。

5.切片操作左闭右开的优点

切片操作的左闭右开原则(即包括起始位置,不包括终止位置)在 Python 中具有多个优点:

  1. 方便计算子序列的长度:由于终止位置不包括在内,你可以通过简单地相减来得到子序列的长度。例如,sequence[start:end] 的长度就是 end - start
my_list = [0, 1, 2, 3, 4, 5]
start = 1
end = 4
sliced_list = my_list[start:end]

# 计算子序列长度
length = end - start
print(length)  # 输出结果:3
  1. 方便连接相邻的切片:左闭右开原则使得相邻的子序列可以顺利连接起来,而不会重复包含共同的边界元素。例如,sequence[:i]sequence[i:] 两个子序列可以完美地连接起来,重建原序列:
my_list = [0, 1, 2, 3, 4, 5]
i = 3
first_slice = my_list[:i]
second_slice = my_list[i:]

# 将两个切片连接起来
new_list = first_slice + second_slice
print(new_list)  # 输出结果:[0, 1, 2, 3, 4, 5]
  1. 避免特殊处理序列末尾的情况:左闭右开原则使得在切片时,无需特殊处理序列末尾的情况。例如,sequence[i:j]sequence[j:k] 两个子序列,当 j 等于序列的长度时,子序列 sequence[j:k] 会自然地成为空序列,而无需额外处理。
my_list = [0, 1, 2, 3, 4, 5]
j = len(my_list)
second_slice = my_list[j:]

print(second_slice)  # 输出结果:[]

综上所述,切片操作的左闭右开原则为我们提供了方便的计算方法,简化了代码编写,并提高了代码的可读性。

6.切片练习题

1.判断是否是回文

要判断一个字符串是否是回文(即正读和反读都相同的字符串),你可以将原始字符串与其翻转后的字符串进行比较。如果它们相同,那么该字符串就是回文。以下是一个使用 Python 的示例:

def is_palindrome(s: str) -> bool:
    return s == s[::-1]

# 测试
test_string_1 = "racecar"
print(is_palindrome(test_string_1))  # 输出结果:True

test_string_2 = "hello"
print(is_palindrome(test_string_2))  # 输出结果:False

在这个例子中,我们定义了一个名为 is_palindrome 的函数,该函数接受一个字符串参数 s。使用切片操作 s[::-1] 可以将字符串翻转。然后我们比较原始字符串 s 和翻转后的字符串是否相同,以确定它是否是回文。如果字符串是回文,函数返回 True,否则返回 False

请注意,这个示例是大小写敏感的。如果你希望在处理大小写时忽略大小写差异,可以在进行比较之前将原始字符串和翻转字符串都转换为小写(或大写):

def is_palindrome_case_insensitive(s: str) -> bool:
    lower_s = s.lower()
    return lower_s == lower_s[::-1]

# 测试
test_string_1 = "Racecar"
print(is_palindrome_case_insensitive(test_string_1))  # 输出结果:True

在这个例子中,我们使用 s.lower() 方法将字符串 s 转换为小写形式,并将其与翻转后的小写字符串进行比较。这样,我们得到的回文判断结果将忽略大小写差异。

2.将1d2c3b4a转换成abcd

使用切片操作,可以轻松地从原始字符串中提取需要的字符。在这个例子中,我们需要从 1d2c3b4a 中提取 d、c、b、a 这四个字符,然后将它们组合成新字符串 abcd。我们可以如下所示进行操作:

orig_string = "1d2c3b4a"
sliced_string = orig_string[1::2]
reversed_string = sliced_string[::-1]

print(reversed_string)  # 输出结果:abcd

首先,我们使用切片操作 orig_string[1::2] 从原始字符串的下标 1(即第二个字符)开始,以步长为 2 的方式提取字符。这将提取出字符串 "dcba"。

接下来,我们使用切片操作 sliced_string[::-1] 将提取的字符串翻转,得到最终的字符串 "abcd"。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力毕业的每一天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值