news 2026/10/14 5:47:54

Python 核心知识 · 第 02 讲字符串 str:对象机制、索引切片、Unicode、常用方法、性能分析与编程实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python 核心知识 · 第 02 讲字符串 str:对象机制、索引切片、Unicode、常用方法、性能分析与编程实现

本讲使用 Python 3,重点掌握字符串的内部行为,而不只是记住split()、replace()等方法。

一、字符串的本质

在 Python 中,字符串是str类型的对象,用于表示 Unicode 文本序列。

s = "Hello Python" print(type(s)) print(len(s)) print(id(s))

输出的前两行:

<class 'str'> 12

第三行是对象身份相关的整数,其具体值因运行环境而异。

字符串有三个核心特征:

  1. 有序:字符具有确定的位置。

  2. 不可变:创建后不能原地修改字符。

  3. 可迭代:可以使用for逐个访问字符。

例如:

s = "robot" s[0] = "R"

会产生:

TypeError: 'str' object does not support item assignment

正确操作:

s = "robot" s = "R" + s[1:] print(s) # Robot

这不是修改原来的字符串,而是构造新的字符串对象,再让变量s指向它。

注意,即使执行s += "!",从语义上仍然是重新绑定,而不是在原字符串上增加字符。

二、字符串索引与切片

2.1 正向索引和负向索引

字符串中的字符可以从两个方向定位。

s = "PYTHON" print(s[0]) # P print(s[2]) # T print(s[-1]) # N print(s[-3]) # H

如果索引超过有效范围:

print(s[10])

会抛出IndexError。

2.2 切片s[start:stop:step]

三个参数分别表示:

  • start:开始位置,包含。

  • stop:结束位置,不包含。

  • step:移动步长,可以为负数。

s = "PYTHON" print(s[1:4]) # YTH print(s[:3]) # PYT print(s[3:]) # HON print(s[::2]) # PTO print(s[::-1]) # NOHTYP print(s[-4:-1]) # THO

为什么s[1:4]不包含索引 4?

因为 Python 使用左闭右开区间,这使切片长度在默认步长为 1 时可以直接计算:

\[ \text{长度}=\text{stop}-\text{start} \]

例如s[1:4]有 3 个字符。

几个重要边界条件:

s = "abc" print(s[0:100]) # abc print(s[3:3]) # 空字符串 print(s[-100:2]) # ab

切片越界通常不会抛出异常,但单个索引越界会。

此外:

s[::0]

会抛出ValueError,因为步长不能为零。

三、字符串常用方法及其返回结果

str的方法很多,但需要按用途分类,而不是孤立记忆。

类别

方法

作用

查找

find()、rfind()

查找子串位置

查找

index()

查找位置,失败时报错

统计

count()

统计非重叠子串出现次数

判断

startswith()、endswith()

前缀和后缀判断

大小写

lower()、upper()

大小写转换

大小写

casefold()

更适合 Unicode 无大小写比较

清理

strip()、lstrip()、rstrip()

去掉首尾指定字符

替换

replace()

替换子串

分割

split()、rsplit()

拆分字符串

合并

join()

合并字符串序列

判断

isdigit()、isalpha()、isalnum()

字符类别判断

3.1find()和index()

s = "robot_control" print(s.find("control")) # 6 print(s.find("camera")) # -1

而:

s.index("camera")

会抛出ValueError。

二者的区别不在于能否查找,而在于没有找到时如何处理。

注意:

print("aaa".count("aa")) # 1

count()默认统计非重叠匹配,不会统计两个相互重叠的"aa"。

3.2strip()的重要陷阱

s = " hello " print(s.strip()) # "hello" print(s.lstrip()) # "hello " print(s.rstrip()) # " hello"

但:

s = "abba" print(repr(s.strip("ab")))

结果:

''

因为strip("ab")的含义不是删除子字符串"ab",而是不断去除首尾属于字符集合{'a', 'b'}的字符。

如果目的是删除确定的前缀、后缀,可使用:

s = "robot_control" print(s.removeprefix("robot_")) # control print(s.removesuffix("_control")) # robot

3.3split()和join()

s = "J1,J2,J3" parts = s.split(",") print(parts) print("-".join(parts))

结果:

['J1', 'J2', 'J3'] J1-J2-J3

split()有一个经常被忽略的区别:

print(" a b ".split()) print(" a b ".split(" "))

结果:

['a', 'b'] ['', 'a', '', 'b', '']

原因是:

  • 不传分隔符时,连续空白会作为一个分隔区域处理,并忽略首尾空白。

  • 显式传入" "时,严格按单个空格拆分,可能产生空字符串。

另一个边界:

print("".split()) # [] print("".split(",")) # ['']

3.4replace()不会修改原字符串

s = "robot_arm" s.replace("_", "-") print(s) # robot_arm

必须接收返回值:

s = s.replace("_", "-") print(s) # robot-arm

这再次体现了字符串不可变的特点。

四、字符串比较与 Unicode 编码

4.1 字符串如何比较大小?

print("8" > "12") # True print("abc" < "abd") # True

字符串按字符的 Unicode 码点顺序逐个比较,并不是先把整段文本转换成数字。

例如:

print(ord("A")) # 65 print(ord("a")) # 97 print(chr(65)) # A

ord()返回单个字符的 Unicode 码点,chr()执行反向转换。

4.2 Unicode、UTF-8、bytes 的区别

最容易混淆的是字符串和字节序列。

  • str:表示 Unicode 文本。

  • bytes:表示字节数据,元素为 0~255 的整数。

  • UTF-8:将 Unicode 文本编码成字节的一种方式。

例如:

text = "机器人" data = text.encode("utf-8") print(len(text)) print(len(data)) print(type(data))

结果:

3 9 <class 'bytes'>

原因是这三个汉字在 UTF-8 中各占 3 个字节。

解码操作:

result = data.decode("utf-8") print(result) # 机器人

需要特别注意:len(str)通常统计 Unicode 码点数量,而不是字节数,也不总是用户肉眼看到的字符数量。

例如:

s = "e\u0301" print(len(s)) # 2

这里由字母e加上一个组合重音符号组成,视觉上可能显示为一个带重音的字母,但len()得到 2。

在文件通信、网络传输、串口协议和机器人控制系统中,必须区分文本与字节数据。

五、字符串格式化与特殊字符

5.1 三种常见格式化方式

name = "Joint1" angle = 90.12345 print("%s: %.2f" % (name, angle)) print("{}: {:.2f}".format(name, angle)) print(f"{name}: {angle:.2f}")

输出均为:

Joint1: 90.12

现代 Python 代码通常优先使用 f-string。

常用格式:

写法

意义

f"{x:.2f}"

固定显示两位小数

f"{x:08d}"

整数宽度为 8,不足补零

f"{x:>10}"

右对齐,宽度为 10

f"{x:<10}"

左对齐

f"{x:^10}"

居中

f"{x:.1%}"

按百分比显示

f"{x!r}"

使用repr()形式

例如:

x = 0.8567 print(f"{x:.1%}") # 85.7%

5.2str()和repr()

s = "a\nb" print(str(s)) print(repr(s))

输出:

a b 'a\nb'

其中:

  • str()更侧重可读展示。

  • repr()更侧重明确表达对象形式,便于调试。

5.3 转义字符与原始字符串

常见转义符:

\n # 换行 \t # 制表符 \\ # 反斜杠 \" # 双引号

Windows 路径需要注意:

path = r"C:\new\robot"print(path)

使用r前缀可以让反斜杠按原始方式处理,适合很多路径和正则表达式场景。但原始字符串不能以奇数个未转义的反斜杠结束。

六、字符串的时间复杂度

下面给出常见操作的数量级,用于判断代码在大量数据下的表现。

设字符串长度为 \(n\),待处理子串长度为 \(k\)。

操作

典型复杂度

说明

s[i]

O(1)

单个字符索引

len(s)

O(1)

长度信息已保存

s[a:b]

O(k)

通常需复制切片内容

s1 + s2

O(n+m)

通常需要构造结果

s[::-1]

O(n)

创建逆序字符串

x in s

与搜索算法和输入有关

不宜一概视为 O(1)

s.split()

通常 O(n)

扫描并创建分段

"".join(parts)

O(结果总长度)

一次构造连接结果

s.replace(a,b)

依赖匹配及替换规模

通常需扫描字符串

为什么不建议反复拼接大字符串?

考虑:

result = "" for i in range(10000): result += str(i)

由于字符串不可变,反复连接可能导致频繁分配和复制,某些情况下累计成本可接近平方级。

更通用的方式:

parts = [] for i in range(10000): parts.append(str(i)) result = "".join(parts)

join()可以一次性构建目标字符串,通常更适合大量片段的拼接。

不过需要理解:CPython 对部分+=场景具有优化,不能简单断言任何反复拼接一定都是 O(n²)。工程上优先使用join(),主要是因为性能更稳定、意图更明确。

七、对象身份、驻留与不可变性

字符串有时会被 Python 复用,这种现象称为字符串驻留(interning)。

a = "python" b = "python" print(a == b) # True

这不代表所有内容相同的字符串都必须是同一个对象。

以下判断不可靠:

print(a is b)

是否共享对象会受到解释器实现、编译优化和运行环境影响。

正确规则是:

  • 比较文本内容用==。

  • 判断是否为同一个对象才使用is。

  • 不依赖字符串驻留结果编写业务逻辑。

在 CPython 中,字符串主要使用灵活的 Unicode 内部表示,根据字符范围选择合适的存储形式。它并不意味着每个字符都固定占用两个字节或四个字节。

本讲编程训练

按照字符串清洗、协议解析、算法实现三个方向递进。

第 1 题:机械臂指令标准化

输入:

" MOVE J1=90 J2=-45 "

输出:

move j1=90 j2=-45

要求去除首尾空白、将连续空白压缩为单个空格,并全部转为小写。

标准答案

command = " MOVE J1=90 J2=-45 " result = " ".join(command.split()).lower() print(result)

解析:

  • split()默认处理连续空白。

  • " ".join(...)用一个空格连接所有部分。

  • lower()将大写字符转为小写。

这是一种适合普通空白分隔指令的文本规范化方式,但如果协议中的引号内空格具有特殊含义,就需要更严格的解析规则。

第 2 题:关节角度数据解析

输入:

" 90.5, -45.2, 0, 180, 30.75, -90 "

要求解析成一个由浮点数组成的列表,结果如下:

[90.5, -45.2, 0.0, 180.0, 30.75, -90.0]

并输出最大角度、最小角度与平均角度。

标准答案

data = " 90.5, -45.2, 0, 180, 30.75, -90 " angles = [] for item in data.split(","): angle = float(item.strip()) angles.append(angle) print("角度列表:", angles) print("最大角度:", max(angles)) print("最小角度:", min(angles)) average = sum(angles) / len(angles) print(f"平均角度:{average:.2f}")

输出:

角度列表: [90.5, -45.2, 0.0, 180.0, 30.75, -90.0] 最大角度: 180.0 最小角度: -90.0 平均角度: 27.68

这段代码假设输入非空,且各项都能转换成数字。对于实际接收的数据,还应逐步加入格式校验与异常处理。

第 3 题:字符串连续字符压缩

编写程序,实现简单的连续字符计数压缩。

示例:

输入:aaabbccccdd 输出:a3b2c4d2

约束:

  • 不能使用第三方库。

  • 必须通过遍历实现。

  • 要考虑空字符串。

  • 分析时间复杂度。

标准答案

def compress(text): if not text: return "" result = [] count = 1 for i in range(1, len(text)): if text[i] == text[i - 1]: count += 1 else: result.append(text[i - 1] + str(count)) count = 1 result.append(text[-1] + str(count)) return "".join(result) print(compress("aaabbccccdd")) print(compress("abc")) print(compress(""))

输出:

a3b2c4d2 a1b1c1

注意最后的空行是因为第三次输出为空字符串。

算法原理:

从第二个字符开始,与前一个字符比较。相同则增加计数,不同则将前一组字符和数量写入结果列表,最后处理末尾的一组字符。

若输入长度为 \(n\):

  • 时间复杂度:O(n),每个字符只需要常数次处理。

  • 空间复杂度:O(n),最坏情况下结果存储空间与输入长度同阶。

这是一种游程编码(Run-Length Encoding)的简化形式。这里主要用于连续字符统计,并不是通用、无歧义的压缩格式,尤其当输入本身包含数字时需要额外设计解码规则。

本讲重点速查

关键问题

正确结论

字符串是否可变?

不可变

索引越界和切片越界是否一样?

不一样

split()与split(" ")是否等价?

不等价

strip("abc")是删除子串吗?

不是,是去掉两端指定字符集合中的字符

replace()是否原地修改?

否

str与bytes是否相同?

否

len("机器人")是多少?

3

len("机器人".encode("utf-8"))是多少?

9

is是否适合比较字符串内容?

不适合,应使用==

大量拼接字符串优先使用什么?

join()

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/14 5:47:29

面试题 - 变压器和耦合电感的区别?

变压器和耦合电感确实看起来很相似(都有两个或多个线圈绕在同一个磁芯上),但它们在设计目的、工作原理和应用场景上有本质区别 变压器的核心功能是高效地传输能量和变换电压/电流,它本身不储存能量 耦合电感的核心功能是储存和释放磁能,并利用耦合实现滤波、滤波或能量传…

作者头像 李华
网站建设 2026/10/14 5:45:53

MiniMax H3长视频实战:从入口可用到批量生产的完整验证指南

上周我在帮团队验证MiniMax H3的长视频能力。第一天非常顺利&#xff0c;模型跑起来了&#xff0c;Web界面能开&#xff0c;提示词敲进去&#xff0c;一段短视频稳稳生成&#xff0c;我当时还发了个消息说“H3已经跑通”。第二天内容团队拿着20秒的脚本过来&#xff0c;我才发现…

作者头像 李华
网站建设 2026/10/14 5:45:35

HEIC转JPG全攻略:原理、工具与批量转换实践

这么开头吧。我上个月整理素材库&#xff0c;结果网盘里躺了三百多张客户发来的产品图&#xff0c;清一色的“.heic”。我电脑是Windows系统&#xff0c;双击一看全是白屏&#xff0c;要不是装过解码插件&#xff0c;这批图基本等于废了。后来逼着自己把HEIC格式从头到尾摸了一…

作者头像 李华
网站建设 2026/10/14 5:45:07

AI私人助理从零搭建指南:工作流、记忆管理与权限安全

1. 先搞清楚"AI私人助理"到底能替你干什么很多人第一次接触AI私人助理这个概念&#xff0c;脑子里浮现的画面要么是科幻电影里那种能陪你聊天、帮你开灯关灯的语音盒子&#xff0c;要么就是觉得这玩意儿离自己太远&#xff0c;是程序员才玩得转的东西。这两种理解都不…

作者头像 李华
网站建设 2026/10/14 5:44:56

AI学会钻空子+万能钥匙开源:小白也能学会网络安全?速收藏!

AI学会钻空子万能钥匙开源&#xff1a;小白也能学会网络安全&#xff1f;速收藏&#xff01; 本文探讨了AI在网络安全领域的双重影响&#xff1a;一方面&#xff0c;AI通过自主学习开始猜密码、找漏洞、绕限制&#xff0c;对多个重要机构网站造成威胁&#xff1b;另一方面&…

作者头像 李华