字符串 — 文字的读取、切片与格式化
字符串 — 文字的读取、切片与格式化
这一章讲透 str——Python 里使用频率最高的数据类型。 原书的章名就叫 String, 它把字符串当成一门手艺:怎么造、怎么按位置取、怎么切一段、怎么拼、怎么 把变量的值嵌进模板,最后附送一张常用方法速查表。这一章的方法你以后每天都在用。
1. 这一章在全书链条里的位置
第 03 章把 str 列为四种基本类型之一,只给了定义;这一章是它的完整展开。
更重要的是,索引和切片是跨类型的通用机制——第 11 章列表、第 12 章元组
用同一套 [start:stop:step] 语法;split 则把你送往列表的世界。
可以说这一章一半是讲字符串,一半是在为后面四种数据结构铺路。
2. 顶层全景:一个字符串的五种操作
造 'Hello, world!' / str(5) / len(s) → 字符串从哪来、多长
取 text[0]、text[-1] → 按位置取一个字符
切 text[0:6]、text[::2]、text[::-1] → 按区间取一段(含倒序)
拼 'Hello' + ', world!' → 字符串相加
嵌 f'Hello, {name}!' → 把变量嵌进模板
图说:造、取、切、拼、嵌,五个动词讲完一整章。3. 核心原理一:创建与度量
字符串的创建方式你已经见过:引号包起来(单、双、三引号等价)1。 这一章补两个新工具:
s4, s5, s6, s7 = str(5), str(6.0), str(True), str(False)
# 得到:'5'、'6.0'、'True'、'False'——什么类型都能转成它的字符串样子原书在这里给了 str() 一个正式身份:字符串的构造器(constructor:负责
「造出这个类型的新对象」的函数)2。
len() 是第二个新工具:传给它一个字符串,返回字符个数。
'Hello, world!' 的 len 是 13,'False' 的 len 是 53。
记住 len() 这个名字——它对后面所有「装多个东西」的类型都管用。
4. 核心原理二:索引 — 从 0 开始的门牌号
想取字符串里的某个字符,用索引(index:字符的位置编号),写法 text[位置]。
Python 的规则:编号从 0 开始,不是 1——第 1 个字符是 text[0],
最后一个是 text[len(text)-1]4。
text = 'Python'
text[0] # 'P',第一个
text[len(text)-1] # 'n',最后一个
text[6] # IndexError: string index out of range —— 越界了!越界是这一章第一种报错:IndexError: string index out of range——
你要的第 6 号位置不存在('Python' 只有 0–5 号)5。
负数索引:从右往左数
上面那个 len(text)-1 写起来太笨。Python 给了更顺手的写法:从 -1 开始
从右往左编号——text[-1] 就是最后一个字符,text[-len(text)] 是第一个6:
正向: P(0) y(1) t(2) h(3) o(4) n(5)
反向: -6 -5 -4 -3 -2 -1原书把这称为 pythonic 的写法——「pythonic」指的是「地道 Python 圈子的
写法」,能用 -1 就别写 len(text)-16。负数越界(text[-7])
同样报 IndexError5。
练习的精髓:正反两套都练一遍
书上的练习很有设计感:给定 'Learning is fun!',先用非负索引做一遍
(第 1 个、最后 1 个、倒数第 2 个),再用负索引把同一组动作重演一遍
(text[-1]、text[-len(text)]、text[-2]、甚至 text[-len(text)+1])
取第二个字符)7。两套走下来,正负索引就焊死在手里了。
5. 核心原理三:切片 — 一次取一段
索引取一个字符;切片(slicing)取一段。语法是 text[start:stop:step],
三个位置各自可省8:
| 位置 | 意思 | 省略时的默认 |
|---|---|---|
| start | 从哪个索引开始取 | 从头(0) |
| stop | 到哪个索引为止(不含它) | 到尾 |
| step | 每隔几个取一个 | 1(挨着取) |
「stop 不含它」是唯一的反直觉点:text[0:6] 取的是 0、1、2、3、4、5 号,
6 号不取——区间是「左闭右开」8。
主线例子:'Python is amazing' 的九连切
原书的演示序列我们完整走一遍,每一刀都有具体产出:
text = 'Python is amazing' # 共 17 个字符,索引 0–16
len(text) # 17 ① text[0:6] → 'Python' 取 0–5 号;stop=6 不含
② text[10:17] → 'amazing' 取 10–16 号
③ text[:6] → 'Python' 省 start,从头来
④ text[10:] → 'amazing' 省 stop,取到尾
⑤ text[:] → 'Python is amazing' 全省,拷贝一份
⑥ text[-7:] → 'amazing' 负索引照样能用:从 -7 号取到尾
⑦ text[:6:2] → 'Pto' step=2:隔一个取一个(P,跳 y,取 t,跳 h,取 o)
⑧ text[10::2] → 'aaig' 从 10 号起隔一个取
⑨ text[::-1] → 'gnizama si nohtyP' step=-1:倒着走 = 整个字符串翻转!九刀输出逐字来自原书9。三刀记忆法:
- 想要末尾一段:负索引 + 省 stop,
text[-7:]——不用算总长度; - 想要隔一个:step=2,
text[:6:2]; - 想要反转:
text[::-1]——面试手写题常客,也是检查回文的第一步。
练习巩固的几刀也值得看:'Learning is fun' 里切 is,答案是
text[9:-4]——正起点配负终点,两套索引混用,合法10。
6. 核心原理四:拼接 — + 号的两副面孔
两个字符串相加,就是首尾接上:
text = 'Hello' + ', world!' # 'Hello, world!'
text = 'Hello'
text += ', world!' # 增强赋值版,等价于 text = text + ', world!'输出都是 Hello, world!11。
但 + 两侧必须都是字符串——这是 Python 与 C++、Java 的一个刻意分歧:
Python 不会自动把数字转成字符串再拼12:
text = 18 + ' years old'
# TypeError: unsupported operand type(s) for +: 'int' and 'str'
# —— 类型错误:+ 不认识 int 和 str 这对组合
text = str(18) + ' years old' # 手动转,输出:18 years old报错 TypeError 是「类型放错了地方」的信号——第 03 章的 str() 转换器
在这里再次登场救火13。记住这条铁律:凡拼接,先保证大家都是 str。
7. 核心原理五:格式化 — f-string 是主角
拼接三五个值就难读了,于是有了字符串格式化:把值嵌进带占位槽的模板。 原书给了两种方式14:
# 方式一:.format(),槽是 {}
'Name: {}, Age: {}'.format(name, age) # 得 'Name: Alice, Age: 30'
# 方式二:f-string(f 前缀),槽里直接写变量名
f'Name: {name}, Age: {age}' # 得 'Name: Bob, Age: 25'两者等价,f-string 是 2016 年 Python 3.6 引入的新写法,更短、槽里能写表达式, 现在的新代码几乎都用它——原书两者都教是负责任,你优先用 f-string 即可14。
f-string 的拿手好戏是配 input():问完名字当场嵌入问候——print(f'Hello, {name}!')
输出 Hello, Neo!15。
格式化还能精修数字
槽里加 :格式说明,就能控制输出形态,原书的三个演示16:
a = 3.1415926
f'{a:.0f}' # '3' .0f:小数点后 0 位(四舍五入)
f'{a:.2f}' # '3.14' .2f:小数点后 2 位
f'{a:.4f}' # '3.1416' .4f:小数点后 4 位
b = 3
f'{b:02d}' # '03' 02d:总宽度 2,缺的前补零
f'{b:04d}' # '0003'
f'{b:08d}' # '00000003'
f'{a:e}' # '3.141593e+00' e:科学计数法:.2f是最常用的一个——金额显示只要两位小数,靠它[^17]。 (注意{a:.0f}是**四舍五入**,而第 03 章的int(3.5)` 是砍小数——两个机制,
别混。)
格式化速查:一个槽位里的三段结构
f-string 槽位的完整结构是 {值:格式说明},格式说明最常见的三种形态16:
| 形态 | 结构拆解 | 例子 |
|---|---|---|
| 小数精度 | 宽度.位数f——f 表示定点小数 | f'{3.1415926:.2f}' → 3.14(四舍五入到两位) |
| 补零对齐 | 0宽度d——d 表示整数,前面 0 表示缺位补零 | f'{3:04d}' → 0003(宽度 4) |
| 科学计数 | e | f'{31415926:e}' → 3.141593e+07 |
记忆钩子:字母决定「哪一族」(f=定点小数、d=整数、e=科学计数),
数字决定「精度或宽度」,前导 0 决定「缺位补不补零」。槽位里还能直接写
小表达式——f'{a+b}' 会先算 a+b 再嵌入;这比先算好存变量再嵌更顺手,
但表达式太复杂时会降低可读性,一行槽位里放一个小运算是上限(这条分寸是我们的建议)。
练习里还有一道「七运算连打」:用 f-string 一次打印 a 和 b 的加减乘除
整除取余幂全部结果,a=1, b=3 时输出七行算式17——它把第 04 章的运算和
这一章的格式化缝在了一起,是全书前半段的小综合。
8. 核心原理六:常用方法 — 一张表带走
str 自带一大批方法——方法的意思是「挂在某个值身上的函数」,
写法是 值.方法名(参数)(注意那个点)。原书演示了八个家族18:
text = 'Python is versatile.'
text.upper() # 'PYTHON IS VERSATILE.' 全大写
text.lower() # 'python is versatile.' 全小写
text.title() # 'Python Is Versatile.' 每个单词首字母大写
text.startswith('Python') # True 以什么开头
text.endswith('versatile') # False 注意:结尾有句号,不等于 'versatile'
text.replace('versatile', 'powerful') # 'Python is powerful.' 替换
text.split() # ['Python', 'is', 'versatile.'] 默认按空格切成列表
text.split('s') # ['Python i', ' ver', 'atile.'] 指定分隔符
text.find('i') # 7 找子串第一次出现的位置
text.find('i', 8) # 10 从 8 号位起找
text.find('i', 17) # -1 找不到返回 -1,不报错!
text.rfind('i') # 18 从右往左找
' whitespace '.lstrip() # 'whitespace ' 剥左端空白
' whitespace '.rstrip() # ' whitespace' 剥右端空白
' whitespace '.strip() # 'whitespace' 两端都剥逐项过三个要点:
find找不到返回 -1 而不是报错——这是它和索引(越界报错)的关键差别。 用返回值前先和 -1 比一下,或者干脆用in先判断('i' in text,True/False)19。split()的产出是列表——它偷偷把你送进第 11 章的地界,这是字符串章 和数据结构章之间的官方通道20。- 大小写敏感:
startswith('python')对'Python is versatile.'得 False—— 大写 P 和小写 p 是两个不同的字符。要忽略大小写得先lower()再比, 这个组合技实战中天天用21。
章末总结表(Table 5.1)在演示之外又补了五个方法,一并带走:capitalize()
(只大写首字母)、join()(split 的逆运算:把列表用分隔符——连接时用的那个记号——接回字符串)、
isdigit()(是否全数字)、isalpha()(是否全字母)、count()(数子串出现次数)
22。
12. 方法速查总表(原书 Table 5.1 全表)
原书章末的总结表值得整表带走——十六个方法,每个配一个例子23:
| 方法 | 干什么 | 例子 → 结果 |
|---|---|---|
str.upper() | 全转大写 | "hello".upper() → "HELLO" |
str.lower() | 全转小写 | "HELLO".lower() → "hello" |
str.capitalize() | 只大写首字母 | "hello world".capitalize() → "Hello world" |
str.title() | 每个单词首字母大写 | "hello world".title() → "Hello World" |
str.strip() | 剥两端空白 | " hello ".strip() → "hello" |
str.replace(old, new) | 替换子串 | "hello world".replace("world", "Python") → "hello Python" |
str.split(sep) | 按分隔符切成列表 | "a,b,c".split(",") → ["a", "b", "c"] |
str.join(iterable) | 用本串作分隔符接列表 | ",".join(["a","b","c"]) → "a,b,c" |
str.find(sub) | 子串首次出现的位置,找不到返回 -1 | "hello".find("e") → 1 |
str.startswith(prefix) | 是否以某前缀开头 | "hello".startswith("he") → True |
str.endswith(suffix) | 是否以某后缀结尾 | "hello".endswith("lo") → True |
str.isdigit() | 是否全是数字 | "123".isdigit() → True |
str.isalpha() | 是否全是字母 | "abc".isalpha() → True |
str.count(sub) | 子串出现次数 | "banana".count("a") → 3 |
三个「表里有、演示里没重点讲」的补充说明:
capitalize与title的分工:前者只管句首("hello world"→"Hello world", 第二个词原样),后者每个词都管("Hello World")。日志句子用前者,人名标题用后者。isdigit是校验用户输入的守门员:input()问数字,先isdigit()再int(), 不然乱输入直接 ValueError(第 03 章的旧坑,这里有了第一重防线)。count与find是一家:都在「扫描子串」,一个数数、一个报位置。
14. 作者的判断与证据
章末的 GenAI 提问区有两问,正文没有作答,我们来答:
- 「为什么修改字符串里的某个字符会报错?」 因为字符串不可变(immutable):
text[0] = 'J'直接TypeError。所有「看似修改」的方法(upper、replace、strip) 其实都造了一个新字符串交给你,原来的纹丝不动——所以必须写text = text.replace('a', 'b')把新串接回名字24。 - 「为什么切片越界不报错?」 切片对越界位置很宽容:
text[0:99]悄悄截到 末尾完事。索引(取一个)严格、切片(取一段)宽松——这是故意的设计25。
这两条合起来解释了第 03 章类型表里「str:Immutable」那一格的真正含义。
具体到代码,不可变长这样:
text = 'Python'
text[0] = 'J' # TypeError: 'str' object does not support item assignment
text = 'J' + text[1:] # 正解:切片取出 'ython',拼上 'J',造一个新串接回名字第二行是正解的标准套路——「改」一个字符串,永远是切片取 + 拼接造 + 重新赋值三步。
replace 方法内部干的就是这件事24。
9. 练习走查:十五个任务,一条「清洗文本」的主线
这一章的练习题量最大(十五个任务),但细看会发现它们能串成一条真实的工作流:
拿到一句原始文本,逐步清洗、解析(把它拆成能处理的小块)它。原书用 'Everyday is a great day' 当材料26,
我们按工作流重排一遍:
① 归一化大小写 text.lower() → 'everyday is a great day'
(日志统计、关键词比对前的标准第一步)
② 校验内容形态 text.startswith('Everyday') → True
text.endswith('day!') → False(句尾没有感叹号)
③ 替换内容 text.replace('great', 'wonderful')
→ 'Everyday is a wonderful day'
④ 切词 text.split()
→ ['Everyday', 'is', 'a', 'great', 'day']
⑤ 定位 text.find('day') → 15(第一次出现)
text.find('day', 16) → 22(跳过一个再找)
text.rfind('day') → 22(从右找,正是最后一次)
⑥ 剥空白 ' padded '.strip() → 'padded'
(input() 收到的输入经常带手滑敲的空格,strip 是保命技)任务①②的输出(True / False / 新串)逐字依据原书26。 第⑤步里 find 连找两次('day' 出现两次:15 号和 22 号位)是「第二个参数指定 搜索起点」的活教材27。
走完全程再回头看:这六步就是真实世界里「清洗一条用户评论」的缩影—— 规范化、校验、替换、切分、定位、去杂。书里没点破这层,但题的编排确实在往 这个方向引。
练习区还有两道 f-string 综合题,机制都不新,但组合方式值得看一眼:
自我介绍题:用一次 print(f'''...''') 打三行自我介绍,三个槽位里各嵌一个
input()——问名字、问年龄、问城市,回答 John / 30 / New York,输出三行
My name is John, / I am 30, and / I live in New York.28。
看点:三引号负责多行,f-string 负责嵌值,input 负责要数据,三样工具各司其职。
价格题:问一个书价再嵌进 The price of the book is $32.3029。
看点:美元符号 $ 在 f-string 里没有特殊含义,直接写即可——容易让人紧张的符号
( $ { } 之类)里,只有花括号是槽位记号,其他全是普通字符。
七运算题见 §7 末段:一个 f-string 模板里连写七个运算槽位,
a=1, b=3 时一次打印七行算式——格式化与第 04 章运算的第一次合流17。
10. split 与 join:一对互逆操作
总结表里的 join 正文没讲,补在这里。它和 split 互为倒影:
words = 'Python is versatile.'.split() # 切:字符串 → 列表
# ['Python', 'is', 'versatile.']
' '.join(words) # 接:列表 → 字符串
# 'Python is versatile.'——用空格把列表接回来
'-'.join(['2024', '05', '01']) # 换分隔符接
# '2024-05-01'读法:分隔符.join(列表)——分隔符是被 join 的那个值,这个顺序新人
总要写反一两次,写反了报错,报错一次就记住了30。
split/join 这对组合拳的典型场景:读进一段文字 → split 成词 → 处理每个词 →
join 拼回文字。第 11 章学会列表遍历之后,这个循环就能真正跑起来。
11. 作者的判断与证据
- 「f-string 与 .format() 是两种主要方式」是对事实的中性陈述14; 原书没有明说推荐哪个,但从演示篇幅看 f-string 是主角(配 input 的例子全用 f-string)15。
- 「Python 不自动做类型转换」是 Python 设计哲学的直接体现 (「显式优于隐式」),书里用与 C++、Java 对比的方式点了出来12。
- 方法选择(这八个家族)是面向「数据处理日常」的取舍:startswith/endswith 配 split/find/strip,正好覆盖清洗日志、解析文本、校验输入三类高频活。
15. 边界与局限
先把「这一章没讲、但你在别处一定撞见」的一句话索引放在最前面(每条后面都标了去向): 字符串是序列(sequence)的第一个实例——「序列」指「有顺序、能按编号取、能切片」 的一类数据;第 11 章列表、第 12 章元组都是序列,索引和切片的规则原封不动地复用。 这一章学的不只是字符串,是后面两章的预科。
join只在总结表出现,正文没讲——它是 split 的逆运算:', '.join(['a', 'b'])得'a, b'。实际使用中它和 split 出场率差不多, 我们在 §10 补了用法。in运算符没讲。'day' in text直接回答 True/False,比 find 再比 -1 顺手得多;它还会在第 07 章分支里当条件用、在第 13 章集合里换一种身份出现。 原书通篇没出现,属于选编的留白,见到别人代码里的in要知道就是这个意思。format()的多槽编号没讲。'{} and {}'.format(a, b)按顺序对槽;'{1} and {0}'.format(a, b)按编号对槽(1 号先填);'{name}'.format(name=x)按名字对槽。f-string 普及后这些用法都退居二线,知道存在即可。- 格式化说明符只是一角。
:.2f、:04d、:e之外还有对齐、千分位、 百分比一整套,书只开了个头;用到再查官方文档的 format specification 一节。 - 没有讲编码。 字符串在内存里怎么存、中文会不会出问题(Unicode、UTF-8 这些词), 本书完全不碰——日常写 Jupyter 遇不到,碰文件时才会撞见;撞见时再去查,不必提前焦虑。
- 没有正则表达式。 复杂的模式匹配(「所有形如 xxx@yyy.zzz 的邮箱地址」这类)
要靠
re模块,那是另一个量级的话题,入门书正确地没碰。 - 方法名记不住怎么办。 不必背:Jupyter 里打出
text.再按 Tab, 编辑器会弹出这个方法名下的全部候选;记个大概发音,剩下交给提示。 (Tab 补全是通用技巧,不在原书里,但和前章的 Jupyter 环境一脉相承。)
16. 可带走的
- 索引从 0 开始,负数从右往左;最后一个字符是
text[-1](别写len(text)-1,那是负数索引出现之前的旧写法)46。 - 越界索引报
IndexError: string index out of range;切片越界不报错、悄悄截断525。 - 切片
text[start:stop:step],stop 不含、三位置都可省;text[::-1]反转字符串9。 - 拼接必须双方都是 str——Python 不自动替你做类型转换;
18 + ' years old'报TypeError,先str(18)13。 - 嵌值进模板用 f-string:
f'Hello, {name}!';数字精修f'{a:.2f}'留两位小数(四舍五入,与 int() 的砍小数不同)1416。 len()数字符数,对后面所有「装多个东西」的类型都管用;str()是字符串构造器23。split()按空格(或指定分隔符)切出列表——字符串通往数据结构的门;join逆运算接回来20。find找不到返回 -1(不报错);startswith/endswith大小写敏感——忽略大小写先.lower()再比1921。- 字符串不可变:replace/upper 都是造新串,要接回变量才生效;想「改」字符,用切片加拼接造新串24。
- 总结表带走:
capitalize/join/isdigit/isalpha/count22。 - f-string 槽位
{值:格式说明}:字母选族(f/d/e)、数字定精度宽度、前导 0 补零; 槽里能写表达式,但一个小运算是可读性上限。 - 索引/切片的规则在第 11 章(列表)、第 12 章(元组)原样复用——这一章吃透, 那两章等于预习了一半。
17. 原文地图
| 主题 | 原书章 | 原文位置 |
|---|---|---|
| str 的定义与用途 | CHAPTER 5: String | text/14-ch05-chapter-5-string.txt:14(搜「sequence of characters enclosed」) |
| 三种引号创建与 str() 构造器 | 同上 | text/14-ch05-chapter-5-string.txt:32(搜「Three strings below are equivalent」) · text/14-ch05-chapter-5-string.txt:42(搜「constructor, or initializor」) |
| len() | 同上 | text/14-ch05-chapter-5-string.txt:51(搜「length of a string」) |
| 0 起索引与越界 | 同上 | text/14-ch05-chapter-5-string.txt:62(搜「starts from 0」) · text/14-ch05-chapter-5-string.txt:87(搜「string index out of range」) |
| 负数索引的 pythonic 写法 | 同上 | text/14-ch05-chapter-5-string.txt:89(搜「pythonic way」) |
| 正反索引练习 | 同上 | text/14-ch05-chapter-5-string.txt:116(搜「Learning is fun」) |
| 切片语法 [start:stop:step] | 同上 | text/14-ch05-chapter-5-string.txt:184(搜「[start:stop:step] notation」) |
| 九连切演示 | 同上 | text/14-ch05-chapter-5-string.txt:193(搜「Python is amazing」) |
| 练习里的 is 切片 | 同上 | text/14-ch05-chapter-5-string.txt:260(搜「Slice is from the text」) |
| 拼接与不自动转换 | 同上 | text/14-ch05-chapter-5-string.txt:293(搜「not auto-convert」) · text/14-ch05-chapter-5-string.txt:306(搜「unsupported operand type」) |
| .format() 与 f-string | 同上 | text/14-ch05-chapter-5-string.txt:320(搜「two main ways」) · text/14-ch05-chapter-5-string.txt:339(搜「f-strings (f'')」) |
| f-string 配 input | 同上 | text/14-ch05-chapter-5-string.txt:348(搜「What is your name?」) |
| 小数位数与补零 | 同上 | text/14-ch05-chapter-5-string.txt:356(搜「Zero decimal points」) · text/14-ch05-chapter-5-string.txt:365(搜「adding extra zeroes」) |
| 七运算连打练习 | 同上 | text/14-ch05-chapter-5-string.txt:412(搜「a = 1, b = 3」) |
| 八个方法家族演示 | 同上 | text/14-ch05-chapter-5-string.txt:449(搜「Python is versatile」) |
| find 的 -1 返回值 | 同上 | text/14-ch05-chapter-5-string.txt:515(搜「-1」) |
| 总结表(含 join 等五方法) | 同上 | text/14-ch05-chapter-5-string.txt:616(搜「Summary of Python string methods」) |
| GenAI 区关于不可变与切片越界的两问 | 同上 | text/14-ch05-chapter-5-string.txt:677(搜「modifying a character」) · text/14-ch05-chapter-5-string.txt:676(搜「out of range」) |
Footnotes
-
出处:「CHAPTER 5: String」第 30–38 段(
text/14-ch05-chapter-5-string.txt:32,搜「Three strings below are equivalent」)。单双三引号三例等价见原文。 ↩ -
出处:「CHAPTER 5: String」第 40–49 段(
text/14-ch05-chapter-5-string.txt:42,搜「constructor, or initializor of strings」)。str(5)/str(6.0)/str(True)/str(False)的产出逐字依据原文。 ↩ ↩2 -
出处:「CHAPTER 5: String」第 51–57 段(
text/14-ch05-chapter-5-string.txt:51,搜「obtain the length of a string」;:56,搜「Hello, world! 13」)。13 与 5 两个长度见原文输出。 ↩ ↩2 -
出处:「CHAPTER 5: String」第 61–64 段(
text/14-ch05-chapter-5-string.txt:62,搜「starts from 0」;:63,搜「text[len(text)-1]」)。「第 1 个字符是 text[0]、最后一个是 text[len(text)-1]」逐字依据原文。 ↩ ↩2 -
出处:「CHAPTER 5: String」第 80–87 段(
text/14-ch05-chapter-5-string.txt:87,搜「string index out of range」)与第 105–113 段(text/14-ch05-chapter-5-string.txt:113,搜「string index out of range」)。正、负两个越界例均见原文。 ↩ ↩2 ↩3 -
出处:「CHAPTER 5: String」第 89–94 段(
text/14-ch05-chapter-5-string.txt:89,搜「pythonic way of accessing the last element」;:91,搜「from the left to the right」)。「text[-1] 是最后一个、text[-len(text)] 是第一个」逐字依据原文。 ↩ ↩2 ↩3 -
出处:「CHAPTER 5: String」第 115–157 段(
text/14-ch05-chapter-5-string.txt:118,搜「Learning is fun」;:155,搜「-len(text)+1」)。八个取字符任务(非负/负索引各四)见原文练习区。 ↩ -
出处:「CHAPTER 5: String」第 183–187 段(
text/14-ch05-chapter-5-string.txt:184,搜「[start:stop:step] notation」;:186,搜「excluded from the substring」)。stop 不含右端的规则逐字依据原文。 ↩ ↩2 -
出处:「CHAPTER 5: String」第 193–243 段(
text/14-ch05-chapter-5-string.txt:196,搜「Extracts 'Python'」;:226,搜「Extracts 'Pto'」;:240,搜「gnizama si nohtyP」)。九刀切片及其输出逐字依据原文演示。 ↩ ↩2 -
出处:「CHAPTER 5: String」第 245–273 段(
text/14-ch05-chapter-5-string.txt:261,搜「text[9:-4]」)。正起点负终点混用见原文练习。 ↩ -
出处:「CHAPTER 5: String」第 279–290 段(
text/14-ch05-chapter-5-string.txt:280,搜「'Hello' + ', world!'」;:287,搜「the same as text = text +」)。两种拼接写法及输出见原文。 ↩ -
出处:「CHAPTER 5: String」第 292–293 段(
text/14-ch05-chapter-5-string.txt:293,搜「will not auto-convert」)。原文:「Not like C++ and Java, Python will not auto-convert other data types to str for concatenation.」 ↩ ↩2 -
出处:「CHAPTER 5: String」第 294–313 段(
text/14-ch05-chapter-5-string.txt:306,搜「unsupported operand type(s) for +: 'int' and 'str'」;:310,搜「str(18) + ' years old'」)。报错原文与修法见原文。 ↩ ↩2 -
出处:「CHAPTER 5: String」第 315–345 段(
text/14-ch05-chapter-5-string.txt:320,搜「two main ways」;:339,搜「f-strings (f'')」)。f-string 为 3.6 引入是通用知识(补充,不在书里)。 ↩ ↩2 ↩3 ↩4 -
出处:「CHAPTER 5: String」第 347–352 段(
text/14-ch05-chapter-5-string.txt:349,搜「Hello, {name}!」)。输入 Neo 输出Hello, Neo!见原文。 ↩ ↩2 -
出处:「CHAPTER 5: String」第 354–380 段(
text/14-ch05-chapter-5-string.txt:356,搜「Zero decimal points of a float」;:365,搜「Make up length of 2」;:374,搜「scientific notation」)。三组格式说明符的输入输出逐字依据原文。 ↩ ↩2 ↩3 -
出处:「CHAPTER 5: String」第 410–441 段(
text/14-ch05-chapter-5-string.txt:412,搜「you'll print」;:424,搜「When a = {a}, b = {b}」)。七行算式输出逐字依据原文。 ↩ ↩2 -
出处:「CHAPTER 5: String」第 449–535 段(
text/14-ch05-chapter-5-string.txt:452,搜「uppercase, lowercase, and titlecase」;:468,搜「startswith('Python')」;:487,搜「replace('versatile', 'powerful')」;:494,搜「default delimeter is a space」;:505,搜「Finding the position」;:531,搜「from the beginning and end」)。八个家族的全部例子与输出见原文。 ↩ -
「find 返回 -1 需先判断;用 in 先测」中的
in用法是通用知识补充(不在书里);find 的 -1 行为见原文第 515 段输出。 ↩ ↩2 -
出处:「CHAPTER 5: String」第 492–502 段(
text/14-ch05-chapter-5-string.txt:497,搜「['Python', 'is', 'versatile.'」)。split 产出列表见原文输出;「官方通道」的说法是我们的观察。 ↩ ↩2 -
出处:「CHAPTER 5: String」第 476–483 段(
text/14-ch05-chapter-5-string.txt:479,搜「starts_with python? is False」)。大小写敏感的确证:token 为小写 'python' 时 startswith 返回 False。 ↩ ↩2 -
出处:「CHAPTER 5: String」第 615–654 段(
text/14-ch05-chapter-5-string.txt:616,搜「Summary of Python string methods」)。总结表五个补充方法及其例子逐字依据原文。 ↩ ↩2 -
出处:「CHAPTER 5: String」第 615–654 段(
text/14-ch05-chapter-5-string.txt:616,搜「Summary of Python string methods」)。表中十六个方法的描述与例子逐字依据原书 Table 5.1;「守门员」「一家」的解读是我们的补充。 ↩ -
补充(不在书里,依据 GenAI 提问与通用知识):字符串不可变、
text[0]='J'报 TypeError,原书正文未讲,只在第 677 段(text/14-ch05-chapter-5-string.txt:677,搜「modifying a character」)作为提问出现;答案依据 Python 官方文档对 str 不可变性的定义。 ↩ ↩2 ↩3 -
补充(不在书里,来自通用知识):切片对越界宽容是 Python 的既定行为,原书正文未讲,第 676 段(
text/14-ch05-chapter-5-string.txt:676,搜「out of range」)把它列为 GenAI 提问。 ↩ ↩2 -
出处:「CHAPTER 5: String」第 537–613 段(
text/14-ch05-chapter-5-string.txt:539,搜「Everyday is a great day」;:542,搜「text.upper()」;:557,搜「startswith('Everyday')」;:576,搜「replace('great', 'wonderful')」;:581,搜「text.split()」)。练习区十五个任务的输出逐字依据原文;「清洗用户评论」的工作流解读是我们的重组。 ↩ ↩2 -
出处:「CHAPTER 5: String」第 590–597 段(
text/14-ch05-chapter-5-string.txt:590,搜「first occurance」;:594,搜「text.find('day', 6)」;:597,搜「text.rfind('day')」)。find 带起点参数与 rfind 的用法见原文。 ↩ -
出处:「CHAPTER 5: String」第 382–400 段(
text/14-ch05-chapter-5-string.txt:389,搜「My name is {input」;:394,搜「What is your name? John」)。三行输出与三个输入逐字依据原文。 ↩ -
出处:「CHAPTER 5: String」第 402–408 段(
text/14-ch05-chapter-5-string.txt:405,搜「The price of the book is ${price}」)。$直接出现在 f-string 文本里见原文。 ↩ -
补充(不在书里,来自通用知识):
str.join(iterable)的签名与「分隔符在前」的顺序依据 Python 官方文档;原书总结表只给了','.join(["a","b","c"])的例子(text/14-ch05-chapter-5-string.txt:635,搜「join(iterable)」)。 ↩