Python数据结构-序列操作


在 Python 中,序列(Sequence) 是一类有序的数据结构,元素按位置排列,可通过索引访问。常见的序列类型包括:列表(list)字符串(str)元组(tuple)range 对象。尽管这些类型的用途不同(如列表可变、字符串不可变),但它们共享一套核心的序列操作,包括索引、切片、拼接等。

一、序列的共性:核心操作

所有序列都支持以下基础操作,语法完全一致。我们以列表[1,2,3,4,5])、字符串"hello")、元组(10,20,30,40))为例说明。

1. 索引(Indexing):访问单个元素

序列中的每个元素都有一个位置编号(索引),可通过 序列[索引] 访问对应元素。

  • 正向索引:从左到右,第一个元素索引为 0,第二个为 1,依次递增。
  • 反向索引:从右到左,最后一个元素索引为 -1,倒数第二个为 -2,依次递减。

示例

# 列表
lst = [1, 2, 3, 4, 5]
print(lst[0])   # 正向索引:第一个元素 → 1
print(lst[-1])  # 反向索引:最后一个元素 → 5

# 字符串(字符即元素)
s = "hello"
print(s[2])     # 第三个字符 → 'l'
print(s[-2])    # 倒数第二个字符 → 'l'

# 元组
tpl = (10, 20, 30, 40)
print(tpl[1])   # 第二个元素 → 20
print(tpl[-3])  # 倒数第三个元素 → 20

注意:若索引超出序列长度(如访问长度为5的序列的索引5-6),会抛出 IndexError

2. 切片(Slicing):访问子序列

切片用于从序列中截取连续的子序列,语法:序列[start:end:step],返回一个新的序列(不修改原序列)。

  • start:起始索引(包含该位置元素,默认0);
  • end:结束索引(不包含该位置元素,默认序列长度);
  • step:步长(每次跳过的元素数,默认1,可为负数表示反向截取)。

基础用法(step=1)

lst = [1, 2, 3, 4, 5]

# 截取索引1到3(含1,不含3)的元素
print(lst[1:3])  # → [2, 3]

# 省略start(从开头截取到end)
print(lst[:3])   # → [1, 2, 3](等价于lst[0:3])

# 省略end(从start截取到末尾)
print(lst[2:])   # → [3, 4, 5](等价于lst[2:5],因长度为5)

# 省略start和end(复制整个序列)
print(lst[:])    # → [1, 2, 3, 4, 5]

步长控制(step>1 或 step<0)

lst = [1, 2, 3, 4, 5, 6, 7]

# step=2:每隔1个元素取1个(从0开始)
print(lst[::2])  # → [1, 3, 5, 7]

# step=-1:反向截取(倒序)
print(lst[::-1]) # → [7, 6, 5, 4, 3, 2, 1]

# 反向+指定范围:从索引5到1(反向取,含5不含1)
print(lst[5:1:-1])  # → [6, 5, 4, 3]

注意:切片时若 start/end 超出序列长度,会自动截断(不会报错)。例如 lst[1:10] 等价于 lst[1:](若序列长度为5)。

3. 序列相加(拼接)

+ 号可将两个同类型的序列拼接为一个新序列(不修改原序列)。

# 列表+列表
lst1 = [1, 2]
lst2 = [3, 4]
print(lst1 + lst2)  # → [1, 2, 3, 4]

# 字符串+字符串
s1 = "hello"
s2 = "world"
print(s1 + s2)      # → "helloworld"

# 元组+元组
tpl1 = (10, 20)
tpl2 = (30, 40)
print(tpl1 + tpl2)  # → (10, 20, 30, 40)

注意:不同类型的序列不能相加(如列表+字符串会报错)。

4. 序列相乘(重复)

* 号可将序列重复 n 次,生成一个新序列(n 为非负整数)。

# 列表重复
print([0] * 3)      # → [0, 0, 0](初始化3个0的列表)
print([1, 2] * 2)   # → [1, 2, 1, 2]

# 字符串重复
print("ab" * 3)     # → "ababab"

# 元组重复
print((10,) * 4)    # → (10, 10, 10, 10)(注意单元素元组需加逗号)

特殊用法:初始化指定长度的空列表(后续填充数据):

empty_lst = [None] * 5  # → [None, None, None, None, None]

5. 成员资格检查(in / not in)

in 判断元素是否在序列中,not in 判断是否不在,返回布尔值 True/False

# 列表
lst = [1, 2, 3]
print(2 in lst)      # → True
print(4 not in lst)  # → True

# 字符串(检查子串是否存在)
s = "hello"
print("ll" in s)     # → True("ll"是s的子串)
print("x" not in s)  # → True

# 元组
tpl = (10, 20, 30)
print(20 in tpl)     # → True

6. 内置函数(序列通用)

  • len(seq):返回序列的长度(元素个数)。
  • max(seq):返回序列中的最大值(元素需可比较,如数值、字符)。
  • min(seq):返回序列中的最小值。
  • sum(seq):返回序列中所有元素的和(仅适用于数值序列,如列表、元组)。

示例

lst = [3, 1, 4, 2]
print(len(lst))   # → 4(长度)
print(max(lst))   # → 4(最大值)
print(min(lst))   # → 1(最小值)
print(sum(lst))   # → 10(总和)

s = "python"
print(len(s))     # → 6(字符数)
print(max(s))     # → 'y'(字符ASCII值最大)
print(min(s))     # → 'h'(字符ASCII值最小)

二、可变序列 vs 不可变序列

序列按是否可修改元素分为两类,操作上有差异: - 不可变序列:字符串(str)、元组(tuple)、range。元素一旦创建不能修改,若尝试通过索引赋值会报错。

s = "hello"
s[0] = "H"  # 报错:TypeError(字符串不可修改)

tpl = (1, 2, 3)
tpl[0] = 0  # 报错:TypeError(元组不可修改)
  • 可变序列:列表(list)。元素可通过索引修改、新增或删除。
lst = [1, 2, 3]
lst[0] = 0      # 修改元素 → [0, 2, 3]
lst.append(4)   # 新增元素 → [0, 2, 3, 4]
del lst[1]      # 删除元素 → [0, 3, 4]

总结

序列是 Python 中最基础的数据结构,核心操作(索引、切片、拼接等)适用于列表、字符串、元组等类型,掌握这些操作能高效处理有序数据。关键区别在于:

  • 所有序列共享索引、切片、相加、相乘、成员检查等操作;
  • 列表是可变序列,支持元素修改;字符串和元组是不可变序列,元素不能直接修改。

通过组合这些操作,可以灵活处理各种序列数据(如提取子串、截取列表片段、检查元素是否存在等)。

Python字符串

Python 中的字符串(str) 是由单个字符组成的不可变序列,用于表示文本数据。它是 Python 中最常用的数据类型之一,支持丰富的操作和方法,适用于文本处理、用户交互等场景。

一、字符串的定义与创建

字符串用单引号('双引号("三引号('''""" 包裹,三种方式功能一致,主要用于灵活处理包含引号的文本。

1. 基本创建方式

# 单引号
s1 = 'hello'

# 双引号(与单引号无区别,适合字符串内包含单引号)
s2 = "it's a cat"  # 字符串内有单引号,用双引号包裹更方便

# 三引号(支持多行字符串,保留换行和缩进)
s3 = '''第一行
第二行
    第三行(带缩进)'''

print(s3)
# 输出:
# 第一行
# 第二行
#     第三行(带缩进)

2. 空字符串与转义字符

  • 空字符串:不含任何字符的字符串,用 ''"" 表示。
empty_str = ""
print(len(empty_str))  # 0(长度为0)
  • 转义字符:用反斜杠 \ 表示特殊字符(如换行、引号等),常见转义字符:
转义字符 含义 示例 输出
\n 换行 print("a\n b") a 换行 b
\t 制表符(Tab) print("a\tb") a b(间隔Tab)
\' 单引号 print('it\'s') it's
\" 双引号 print("\"hello\"") "hello"
\\ 反斜杠 print("a\\b") a\b

3. 原始字符串(避免转义)

在字符串前加 rR,表示原始字符串,其中的转义字符不会被解析(常用于文件路径、正则表达式等)。

# 普通字符串中 \n 会被解析为换行
print("C:\new\test.txt")
# 输出(意外换行):
# C:
# ew\test.txt

# 原始字符串中 \ 不转义
print(r"C:\new\test.txt")  # 输出:C:\new\test.txt(正确显示路径)

二、字符串的核心特性:不可变性

字符串一旦创建,其字符不可修改(修改操作会创建新字符串,原字符串不变)。

s = "hello"
# s[0] = 'H'  # 报错:TypeError(字符串不可修改)

# 若需"修改",需创建新字符串
new_s = 'H' + s[1:]  # 拼接新字符和原字符串的子串
print(new_s)  # "Hello"

三、字符串的基础操作(与序列一致)

字符串是序列的一种,支持序列通用操作:索引、切片、拼接、重复、成员检查等。

1. 索引(访问单个字符)

  • 正向索引:从左到右,第一个字符索引为 0,依次递增。
  • 反向索引:从右到左,最后一个字符索引为 -1,依次递减。
s = "Python"
print(s[0])   # 正向索引:第一个字符 → 'P'
print(s[-1])  # 反向索引:最后一个字符 → 'n'
print(s[3])   # 索引3 → 'h'

2. 切片(访问子串)

语法:s[start:end:step],返回从 startend-1 的子串(步长 step 控制间隔)。

s = "abcdef"
print(s[1:4])    # 从索引1到3 → 'bcd'
print(s[:3])     # 从开头到2 → 'abc'
print(s[3:])     # 从3到结尾 → 'def'
print(s[::2])    # 步长2(隔一个取一个)→ 'ace'
print(s[::-1])   # 步长-1(倒序)→ 'fedcba'

3. 拼接与重复

  • 拼接:用 + 连接两个字符串(生成新字符串)。
  • 重复:用 *n 重复字符串 n 次(生成新字符串)。
s1 = "Hello"
s2 = "World"
print(s1 + " " + s2)  # 拼接 → "Hello World"
print("-" * 10)       # 重复10次 → "----------"

4. 成员检查(in / not in

判断子串是否在字符串中,返回布尔值。

s = "Python is fun"
print("is" in s)      # True("is"是子串)
print("java" not in s)  # True("java"不是子串)

5. 内置函数(序列通用)

  • len(s):返回字符串长度(字符个数)。
  • max(s) / min(s):返回 ASCII 码最大/最小的字符。
  • str(obj):将其他类型转换为字符串。
s = "hello"
print(len(s))    # 5(长度为5)
print(max(s))    # 'o'(ASCII码最大)
print(str(123))  # "123"(整数转字符串)

四、字符串的常用方法(高频)

字符串提供了大量内置方法(均返回新字符串,不修改原字符串),以下是最常用的类别:

1. 大小写转换

方法 功能描述 示例 结果
upper() 转换为全大写 "Hello".upper() "HELLO"
lower() 转换为全小写 "HELLO".lower() "hello"
capitalize() 首字母大写,其余小写(仅针对首个字符) "hello world".capitalize() "Hello world"
title() 每个单词首字母大写(以空格/标点分隔) "hello world".title() "Hello World"
swapcase() 大小写互换 "Hello".swapcase() "hELLO"

2. 查找与替换

方法 功能描述 示例 结果
find(sub, start=0, end=len) 查找子串 sub,返回首次出现的索引;未找到返回 -1 "abcabc".find("ab") 0
index(sub, start=0, end=len) find,但未找到时抛出 ValueError "abcabc".index("ab", 1) 3
rfind(sub) / rindex(sub) 从右侧开始查找(返回首次出现的索引,仍从左计数) "abcabc".rfind("ab") 3
replace(old, new, count=-1) new 替换 oldcount 为替换次数(默认全部) "aaa".replace("a", "b", 2) "bba"

3. 判断类方法(返回布尔值)

方法 功能描述 示例 结果
startswith(prefix) 是否以 prefix 开头 "hello".startswith("he") True
endswith(suffix) 是否以 suffix 结尾 "hello".endswith("lo") True
isalpha() 是否全为字母(无数字、空格等) "Hello".isalpha() True
isdigit() 是否全为数字 "123".isdigit() True
isalnum() 是否由字母和数字组成(无其他字符) "abc123".isalnum() True
isspace() 是否全为空白字符(空格、\t、\n等) " \t\n".isspace() True
islower() / isupper() 是否全为小写/大写 "hello".islower() True

4. 修剪与对齐

方法 功能描述 示例 结果
strip(chars=None) 移除首尾指定字符(默认移除空白字符:空格、\t、\n等) " hello ".strip() "hello"
lstrip(chars=None) 移除左侧指定字符 "###hello".lstrip("#") "hello"
rstrip(chars=None) 移除右侧指定字符 "hello###".rstrip("#") "hello"
center(width, fillchar=' ') 居中对齐,总长度为 width,不足用 fillchar 填充 "hi".center(5, "*") "*hi**"
ljust(width, fillchar=' ') 左对齐 "hi".ljust(5, "-") "hi---"
rjust(width, fillchar=' ') 右对齐 "hi".rjust(5, "-") "---hi"

5. 分割与连接

方法 功能描述 示例 结果
split(sep=None, maxsplit=-1) sep 分割字符串为列表,maxsplit 为最大分割次数(默认全部分割) "a,b,c".split(",") ["a", "b", "c"]
rsplit(sep=None, maxsplit=-1) 从右侧开始分割(结果顺序不变) "a/b/c".rsplit("/", 1) ["a/b", "c"]
splitlines(keepends=False) 按换行符分割(\n\r\n 等),keepends=True 保留换行符 "a\nb\nc".splitlines() ["a", "b", "c"]
join(iterable) 用字符串连接可迭代对象(如列表)中的元素(高效拼接多个字符串 "-".join(["a", "b", "c"]) "a-b-c"

五、字符串格式化(拼接与格式化文本)

字符串格式化用于动态生成带变量的文本,Python 提供三种常用方式:

1. f-字符串(Python 3.6+,推荐)

在字符串前加 fF,用 {变量} 嵌入表达式(最简洁、高效)。

name = "小明"
age = 18
# 嵌入变量
print(f"姓名:{name},年龄:{age}")  # 输出:姓名:小明,年龄:18

# 嵌入表达式
print(f"明年年龄:{age + 1}")  # 输出:明年年龄:19
print(f"大写姓名:{name.upper()}")  # 输出:大写姓名:小明(假设name是中文,upper()不生效)

2. str.format() 方法

{} 作为占位符,通过 format() 传入参数(兼容性好,支持复杂格式化)。

# 按位置传参
print("姓名:{},年龄:{}".format("小红", 20))  # 姓名:小红,年龄:20

# 按索引传参
print("第二个参数:{1},第一个参数:{0}".format("a", "b"))  # 第二个参数:b,第一个参数:a

# 按关键字传参
print("身高:{h}m,体重:{w}kg".format(h=1.75, w=60))  # 身高:1.75m,体重:60kg

# 格式化数字(保留2位小数)
print("圆周率:{:.2f}".format(3.14159))  # 圆周率:3.14

3. % 格式化(旧式,不推荐但仍可见)

% 作为占位符,类似 C 语言的 printf

name = "小刚"
age = 19
print("姓名:%s,年龄:%d" % (name, age))  # 姓名:小刚,年龄:19
# %s:字符串,%d:整数,%f:浮点数(如%.2f保留2位小数)

总结

字符串是 Python 中处理文本的核心类型,其核心特性和操作包括:

  • 不可变性:修改需创建新字符串。
  • 序列操作:支持索引、切片、拼接等。
  • 丰富方法:大小写转换、查找替换、分割连接等,覆盖大部分文本处理需求。
  • 格式化:f-字符串简洁高效,是首选方式。

掌握字符串操作是处理用户输入、文本解析、日志生成等场景的基础,建议结合实际需求多练习常用方法(如 split()join()replace() 等)。

Python包含6种内建序列,即列表、元组、字符串、Unicode字符串、buffer对象和xrange对象。本章重点讨论最常用的两种,即列表和元组。

通用序列操作

Python中所有序列都可以进行一些特定操作,包括索引(indexing)、分片(slicing)、序列相加(adding)、乘法(multiplying)、成员资格、长度、最小值和最大值。

一、索引

序列中的所有元素都有编号,也就是索引。索引从0开始递增,0指向第一个元素。也可以用负数进行索引,-1指向倒数第一个元素。

>>> string = '你好,我是左老师'
>>> string[0]
'你'
>>> string[1]
'好'
>>> string[-1]
'师'
>>> 

获取用户输入时,也可以用到索引。比如,你只想获取用户输入的第四位。

>>> x = input()[3]
abcdef
>>> x
'd'
>>>

二、切片

索引用于访问单个元素,切片可以访问指定范围内的元素。需要使用两个索引来表示范围,用冒号分割。

第一个索引是包含的第一个元素的编号,第二个索引是切片后余下的第一个元素的编号

1、正序切片
>>> date = '2021-12-06'
>>> year = date[0:4]
>>> year
'2021'
2、倒序切片

由于右侧索引所在元素并不在切片范围内,当使用负数索引定位序列末尾元素时,会发现永远无法获取最后一个元素。所以我们可以省略第二个索引,代表索引1及其之后的元素。

>>> date = '2021-12-06'
>>> day = date[-2:-1]
>>> day
'0'
>>> day = date[-2:]
>>> day
'06'
3、省略索引
>>> date = '2021-12-06'
>>> y_m = date[:7]
>>> y_m
'2021-12'
>>> y_m_d = date[:]
>>> y_m_d
'2021-12-06'
>>> 
4、切片步长

[索引1:索引2:步长]

#步长默认为1

(1)步长为正数时,从左往右提取元素
>>> num = [0,1,2,3,4,5,6,7,8,9]
>>> odd = num[1::2]
>>> odd
[1, 3, 5, 7, 9]
>>> even = num[::2]
>>> even
[0, 2, 4, 6, 8]
(2)步长为负数时,从右往左提取元素
>>> num = 'abcde'
>>> i = num[::-1]
>>> i
'edcba'

三、序列相加

注意不能拼接不同类型的序列

>>> str1 = '你'
>>> str2 = '今天'
>>> str3 = '吃饭了吗?'
>>> str = str1 + str2 + str3
>>> str
'你今天吃饭了吗?'

四、乘法

运算符:*

当序列与乘数x相乘时,将会重复这个序列x此来创建一个新序列

>>> '今天天气好晴朗'*5
'今天天气好晴朗今天天气好晴朗今天天气好晴朗今天天气好晴朗今天天气好晴朗'
>>> [None]*10
[None, None, None, None, None, None, None, None, None, None]

五、成员资格

检查特定的值是否包含在序列中,可使用运算符:in

它会检查是否满足指定条件,并返回布尔值:True或False

>>> list = [1,12,123,1234]
>>> 1234 in list
True
>>> list = [1,2,33]
>>> 3 in list
False
>>> list = [[1,2,33],1,2,33]
>>> [1,2,33] in list
True
>>>