编程语言研究书库

字符串 — 文字的读取、切片与格式化

字符串 — 文字的读取、切片与格式化

这一章讲透 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)
科学计数ef'{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'      两端都剥

逐项过三个要点:

  1. find 找不到返回 -1 而不是报错——这是它和索引(越界报错)的关键差别。 用返回值前先和 -1 比一下,或者干脆用 in 先判断('i' in text,True/False)19。
  2. split() 的产出是列表——它偷偷把你送进第 11 章的地界,这是字符串章 和数据结构章之间的官方通道20。
  3. 大小写敏感: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. 可带走的

  1. 索引从 0 开始,负数从右往左;最后一个字符是 text[-1](别写 len(text)-1,那是负数索引出现之前的旧写法)46。
  2. 越界索引报 IndexError: string index out of range;切片越界不报错、悄悄截断525。
  3. 切片 text[start:stop:step],stop 不含、三位置都可省;text[::-1] 反转字符串9。
  4. 拼接必须双方都是 str——Python 不自动替你做类型转换;18 + ' years old' 报 TypeError,先 str(18)13。
  5. 嵌值进模板用 f-string:f'Hello, {name}!';数字精修 f'{a:.2f}' 留两位小数(四舍五入,与 int() 的砍小数不同)1416。
  6. len() 数字符数,对后面所有「装多个东西」的类型都管用;str() 是字符串构造器23。
  7. split() 按空格(或指定分隔符)切出列表——字符串通往数据结构的门;join 逆运算接回来20。
  8. find 找不到返回 -1(不报错);startswith/endswith 大小写敏感——忽略大小写先 .lower() 再比1921。
  9. 字符串不可变:replace/upper 都是造新串,要接回变量才生效;想「改」字符,用切片加拼接造新串24。
  10. 总结表带走:capitalize/join/isdigit/isalpha/count22。
  11. f-string 槽位 {值:格式说明}:字母选族(f/d/e)、数字定精度宽度、前导 0 补零; 槽里能写表达式,但一个小运算是可读性上限。
  12. 索引/切片的规则在第 11 章(列表)、第 12 章(元组)原样复用——这一章吃透, 那两章等于预习了一半。

17. 原文地图

主题原书章原文位置
str 的定义与用途CHAPTER 5: Stringtext/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

  1. 出处:「CHAPTER 5: String」第 30–38 段(text/14-ch05-chapter-5-string.txt:32,搜「Three strings below are equivalent」)。单双三引号三例等价见原文。 ↩

  2. 出处:「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

  3. 出处:「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

  4. 出处:「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

  5. 出处:「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

  6. 出处:「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

  7. 出处:「CHAPTER 5: String」第 115–157 段(text/14-ch05-chapter-5-string.txt:118,搜「Learning is fun」;:155,搜「-len(text)+1」)。八个取字符任务(非负/负索引各四)见原文练习区。 ↩

  8. 出处:「CHAPTER 5: String」第 183–187 段(text/14-ch05-chapter-5-string.txt:184,搜「[start:stop:step] notation」;:186,搜「excluded from the substring」)。stop 不含右端的规则逐字依据原文。 ↩ ↩2

  9. 出处:「CHAPTER 5: String」第 193–243 段(text/14-ch05-chapter-5-string.txt:196,搜「Extracts 'Python'」;:226,搜「Extracts 'Pto'」;:240,搜「gnizama si nohtyP」)。九刀切片及其输出逐字依据原文演示。 ↩ ↩2

  10. 出处:「CHAPTER 5: String」第 245–273 段(text/14-ch05-chapter-5-string.txt:261,搜「text[9:-4]」)。正起点负终点混用见原文练习。 ↩

  11. 出处:「CHAPTER 5: String」第 279–290 段(text/14-ch05-chapter-5-string.txt:280,搜「'Hello' + ', world!'」;:287,搜「the same as text = text +」)。两种拼接写法及输出见原文。 ↩

  12. 出处:「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

  13. 出处:「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

  14. 出处:「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

  15. 出处:「CHAPTER 5: String」第 347–352 段(text/14-ch05-chapter-5-string.txt:349,搜「Hello, {name}!」)。输入 Neo 输出 Hello, Neo! 见原文。 ↩ ↩2

  16. 出处:「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

  17. 出处:「CHAPTER 5: String」第 410–441 段(text/14-ch05-chapter-5-string.txt:412,搜「you'll print」;:424,搜「When a = {a}, b = {b}」)。七行算式输出逐字依据原文。 ↩ ↩2

  18. 出处:「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」)。八个家族的全部例子与输出见原文。 ↩

  19. 「find 返回 -1 需先判断;用 in 先测」中的 in 用法是通用知识补充(不在书里);find 的 -1 行为见原文第 515 段输出。 ↩ ↩2

  20. 出处:「CHAPTER 5: String」第 492–502 段(text/14-ch05-chapter-5-string.txt:497,搜「['Python', 'is', 'versatile.'」)。split 产出列表见原文输出;「官方通道」的说法是我们的观察。 ↩ ↩2

  21. 出处:「CHAPTER 5: String」第 476–483 段(text/14-ch05-chapter-5-string.txt:479,搜「starts_with python? is False」)。大小写敏感的确证:token 为小写 'python' 时 startswith 返回 False。 ↩ ↩2

  22. 出处:「CHAPTER 5: String」第 615–654 段(text/14-ch05-chapter-5-string.txt:616,搜「Summary of Python string methods」)。总结表五个补充方法及其例子逐字依据原文。 ↩ ↩2

  23. 出处:「CHAPTER 5: String」第 615–654 段(text/14-ch05-chapter-5-string.txt:616,搜「Summary of Python string methods」)。表中十六个方法的描述与例子逐字依据原书 Table 5.1;「守门员」「一家」的解读是我们的补充。 ↩

  24. 补充(不在书里,依据 GenAI 提问与通用知识):字符串不可变、text[0]='J' 报 TypeError,原书正文未讲,只在第 677 段(text/14-ch05-chapter-5-string.txt:677,搜「modifying a character」)作为提问出现;答案依据 Python 官方文档对 str 不可变性的定义。 ↩ ↩2 ↩3

  25. 补充(不在书里,来自通用知识):切片对越界宽容是 Python 的既定行为,原书正文未讲,第 676 段(text/14-ch05-chapter-5-string.txt:676,搜「out of range」)把它列为 GenAI 提问。 ↩ ↩2

  26. 出处:「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

  27. 出处:「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 的用法见原文。 ↩

  28. 出处:「CHAPTER 5: String」第 382–400 段(text/14-ch05-chapter-5-string.txt:389,搜「My name is {input」;:394,搜「What is your name? John」)。三行输出与三个输入逐字依据原文。 ↩

  29. 出处:「CHAPTER 5: String」第 402–408 段(text/14-ch05-chapter-5-string.txt:405,搜「The price of the book is ${price}」)。$ 直接出现在 f-string 文本里见原文。 ↩

  30. 补充(不在书里,来自通用知识):str.join(iterable) 的签名与「分隔符在前」的顺序依据 Python 官方文档;原书总结表只给了 ','.join(["a","b","c"]) 的例子(text/14-ch05-chapter-5-string.txt:635,搜「join(iterable)」)。 ↩

On this page