四、字符串(P33–P40)
P33 · 知识点:字符串不可变
【题目】执行 s = "abc"; s[0] = "x" 会?
A. 成功修改,s 变为 "xbc" B. 返回 None C. 静默创建新字符串 D. 抛出 TypeError(字符串是不可变序列,不支持元素赋值)
答案:D
【考点】字符串是不可变(immutable)序列。
【结论】选 D。字符串属于不可变序列,不支持对单个元素进行赋值操作。
【推导过程】 在 Python 中执行 s = "abc" 后,s 指向一个字符串对象。当执行 s[0] = "x" 时,解释器会尝试修改该字符串的第一个字符。由于字符串是不可变类型,其内部数据不允许被修改,因此解释器会抛出 TypeError: 'str' object does not support item assignment。
【逐项辨析】 A. 错误。字符串不可变,无法就地修改,s 不会变为 "xbc"。 D. 正确。字符串是不可变序列,不支持元素赋值,会抛出 TypeError。 C. 错误。Python 不会静默创建新字符串来替代原字符串的某个字符,而是直接抛出异常。 B. 错误。该操作不会返回 None,而是抛出异常。
【知识点】 Python 中的字符串(str)是不可变序列(immutable sequence),这意味着一旦创建,其内容就无法被修改。任何看似“修改”字符串的操作,实际上都是创建了一个新的字符串对象。常见的字符串“修改”方式包括:
- 拼接:s + "x" 会创建新字符串
- 切片重组:s[:1] + "x" + s[2:] 创建新字符串
- replace():str.replace(old, new) 返回新字符串,原字符串不变
- 格式化:f-string、format() 等都生成新字符串 不可变性的优点包括:可作为字典的键、线程安全、可被哈希、便于内存共享(驻留机制)等。
【记忆锚点】 “字符串是铁板一块,想改只能另起炉灶”——不可变对象不能打补丁,只能整体重建。
【易混对比】
| 类型 | 是否可变 | 支持 item assignment | 示例 |
|---|---|---|---|
| 字符串 str | 不可变 | 否,抛 TypeError | s[0] = "x" ❌ |
| 列表 list | 可变 | 是 | lst[0] = 1 ✓ |
| 元组 tuple | 不可变 | 否,抛 TypeError | t[0] = 1 ❌ |
| 字节串 bytes | 不可变 | 否,抛 TypeError | b[0] = 1 ❌ |
| 字节数组 bytearray | 可变 | 是 | ba[0] = 1 ✓ |
换问法:若题目改为执行 lst = ["a", "b", "c"]; lst[0] = "x",结果是什么?——成功修改,lst 变为 ["x", "b", "c"],因为列表是可变类型。
【自测】 执行以下代码,输出结果是什么?
s = "hello"
try:
s[1] = "a"
except TypeError as e:
print(type(e).__name__)答:输出 "TypeError"。因为字符串不可变,s[1] = "a" 会抛出 TypeError,被 except 捕获后打印异常类名。与第 P34 题连考。
【知识关联】
- 同库关联:与 J23(Java String 不可变)对照;与 P34–P40 方法群。
- 实现层:CPython str 不可变;方法返回新串。
- 面试追问:① 为何不可变更安全?② 修改字符串会怎样?
【拓展延伸】
- 变式问法:
s[0]="x"TypeError;s.replace 返回新对象。 - 版本差异:语义稳定。
- 工程注意点:循环修改用 list 再 join;注意编码(Py3 str 为 unicode)。
P34 · 知识点:replace
【题目】"Hello World".replace("World", "Python") 的结果是?
A. 抛异常 B. 原字符串被修改为 "Hello Python" C. "Hello World" D. "Hello Python"
答案:D
【考点】replace 返回新字符串,原字符串不变。
【结论】选 D。str.replace() 返回替换后的新字符串,原字符串保持不变。
【推导过程】 "Hello World".replace("World", "Python") 的调用过程如下:
- 在字符串 "Hello World" 中查找子串 "World"
- 找到匹配后,生成新字符串 "Hello Python"
- 原字符串 "Hello World" 未被修改,新字符串被返回
【逐项辨析】 D. 正确。replace 方法返回替换后的新字符串 "Hello Python"。 B. 错误。字符串不可变,原字符串不会被修改,replace 始终返回新对象。 C. 错误。replace 找到了匹配的子串并执行了替换,不会返回原字符串。 A. 错误。子串 "World" 存在于原字符串中,替换操作不会抛异常。
【知识点】 str.replace(old, new[, count]) 是 Python 字符串的核心方法之一:
- 功能:将字符串中所有出现的 old 子串替换为 new 子串
- 返回值:返回替换后的新字符串,原字符串不变(因为字符串不可变)
- count 参数:可选,指定最大替换次数,如 "a,a,a".replace("a", "b", 1) → "b,a,a"
- 性能考量:对于大量拼接操作,推荐使用 join() 而非多次 replace() 或 +=
字符串不可变性是理解 replace 行为的关键。在 Python 中,所有字符串方法(upper、lower、strip、split 等)都遵循“返回新字符串,原串不变”的原则。
【记忆锚点】 “replace 换汤不换药,老串还在新串走”——replace 生成新字符串,原字符串纹丝不动。
【易混对比】
| 方法 | 操作对象 | 是否修改原对象 | 返回值 | 适用场景 |
|---|---|---|---|---|
| str.replace() | 字符串 | 否(不可变) | 新字符串 | 子串替换 |
| list.remove() | 列表 | 是(就地修改) | None | 删除首个匹配元素 |
| list.pop() | 列表 | 是(就地修改) | 被弹出的元素 | 按索引删除 |
| dict.update() | 字典 | 是(就地修改) | None | 批量更新键值对 |
换问法:若题目问 “执行 s = 'abc'; s = s.replace('a', 'x') 后,id(s) 是否改变?”——答案是 id(s) 会改变,因为 s 指向了新的字符串对象。
【自测】 以下代码的输出是什么?
s = "banana"
print(s.replace("a", "o", 2))
print(s)答:第一行输出 "bonona"(只替换前 2 个 "a"),第二行输出 "banana"(原字符串不变)。与第 P35 题连考。
【知识关联】
- 同库关联:与 P33/P35;replace 全部替换除非 count。
- 实现层:扫描生成新串。
- 面试追问:① 替换不存在子串?② 正则替换用什么?
【拓展延伸】
- 变式问法:
"aaa".replace("aa","b")顺序结果。 - 版本差异:语义稳定。
- 工程注意点:模板替换用 str.format/f-string;正则用 re.sub。
P35 · 知识点:strip
【题目】" hello ".strip() 的结果是?
A. " hello " B. "hello" C. " hello" D. "hello "
答案:B
【考点】strip/lstrip/rstrip 去除空白。
【结论】选 B。strip() 方法去除字符串两端的所有空白字符,返回新字符串。
【推导过程】 " hello ".strip() 的执行过程:
- 从字符串左端开始扫描,去除连续的空格字符
- 从字符串右端开始扫描,去除连续的空格字符
- 中间的空格保留不动
- 返回处理后的新字符串 "hello"
【逐项辨析】 A. 错误。strip() 会去除两端空白,不会返回原字符串。 B. 正确。strip() 去除两端的空格,中间内容保留,结果为 "hello"。 C. 错误。rstrip() 才会只去除右端空白,保留左端空格,得到 " hello"。 D. 错误。lstrip() 才会只去除左端空白,保留右端空格,得到 "hello "。
【知识点】 Python 提供了三个用于去除字符串边界空白的方法:
- str.strip([chars]):去除字符串两端(左侧和右侧)的空白字符(默认)或指定字符集中的字符
- str.lstrip([chars]):仅去除左侧的空白字符或指定字符
- str.rstrip([chars]):仅去除右侧的空白字符或指定字符
默认情况下,这三个方法去除的空白字符包括:空格( )、制表符(\t)、换行符(\n)、回车符(\r)、换页符(\f)、垂直制表符(\v)等。
重要特性:
- 返回新字符串(字符串不可变)
- 可指定自定义字符集:">>hello<<".strip("<>") → "hello"
- 只去除两端的连续匹配字符,中间字符不受影响
【记忆锚点】 “strip 左右开弓,l 管左边 r 管右边”——strip 是两端,lstrip 是左端,rstrip 是右端。
【易混对比】
| 方法 | 作用位置 | 默认去除字符 | 中间字符 | 示例 " a b " |
|---|---|---|---|---|
| strip() | 两端 | 空白字符 | 保留 | "a b" |
| lstrip() | 左端 | 空白字符 | 保留 | "a b " |
| rstrip() | 右端 | 空白字符 | 保留 | " a b" |
| replace(" ", "") | 全局 | 所有空格 | 也去除 | "ab" |
换问法:若题目问 ">>> 'xyzhelloxyz'.strip('xyz')" 的结果是什么?——答案是 "hello",因为 strip 会去除两端连续的 'x'、'y'、'z' 字符。
【自测】 以下代码的输出分别是什么?
s = "\t hello world \n"
print(repr(s.strip()))
print(repr(s.lstrip()))答:s.strip() 输出 "'hello world'"(两端空白去除);s.lstrip() 输出 "'hello world \n'"(仅左端空白去除,右端保留)。注意 repr() 可以显示不可见字符。与第 P36 题连考。
【知识关联】
- 同库关联:与 P33;strip/lstrip/rstrip 与 Java trim 对照。
- 实现层:去空白或指定字符集两端。
- 面试追问:① strip 中间空白?② 与 trim 差异?
【拓展延伸】
- 变式问法:
"xxhi".strip("x")。 - 版本差异:语义稳定。
- 工程注意点:清洗用户输入;注意全角空白。
P36 · 知识点:join
【题目】",".join(["a", "b", "c"]) 的结果是?
A. 抛异常 B. "abc" C. "a b c" D. "a,b,c"
答案:D
【考点】join 以调用者为分隔符拼接序列;与 split 互逆。
【结论】选 D。join() 方法以调用者为分隔符,将可迭代对象中的字符串元素连接成一个新字符串。
【推导过程】 ",".join(["a", "b", "c"]) 的执行过程:
- 分隔符为 ",",可迭代对象为 ["a", "b", "c"]
- 将列表中的三个字符串元素用 "," 连接
- 生成新字符串 "a,b,c" 并返回
【逐项辨析】 D. 正确。join 以 "," 为分隔符连接列表元素,结果为 "a,b,c"。 B. 错误。"abc" 是没有分隔符直接拼接的结果,需要使用空字符串 "".join(["a", "b", "c"])。 C. 错误。"a b c" 是以空格为分隔符连接的结果,不是逗号。 A. 错误。列表元素均为字符串类型,join 操作不会抛异常。
【知识点】 str.join(iterable) 是 Python 中字符串拼接的推荐方法:
- 语法:separator.join(iterable)
- 功能:将可迭代对象中的字符串元素用 separator 连接成一个字符串
- 要求:可迭代对象中的所有元素必须是字符串类型,否则会抛出 TypeError
- 性能优势:join() 预先计算总长度,只分配一次内存,时间复杂度为 O(n);而使用 += 循环拼接会产生大量中间对象,时间复杂度为 O(n²)
常见用法:
- ",".join(lst) —— 逗号分隔
- "".join(lst) —— 无缝拼接
- "\n".join(lst) —— 每行一个元素
- " ".join(lst) —— 空格分隔
与 split() 的互逆关系: "a,b,c".split(",") → ['a', 'b', 'c'] ",".join(['a', 'b', 'c']) → "a,b,c"
【记忆锚点】 “分隔符站中间,join 把两边牵”——调用 join 的是分隔符,参数是被连接的序列。
【易混对比】
| 拼接方式 | 语法 | 是否高效 | 元素类型要求 | 适用场景 |
|---|---|---|---|---|
| join() | sep.join(lst) | 高(O(n)) | 必须是字符串 | 大量拼接 |
| += 循环 | s += item | 低(O(n²)) | 自动转字符串 | 少量拼接 |
| f-string | f"{a}{b}" | 高 | 任意(自动转换) | 格式化输出 |
| % 格式化 | "%s%s" % (a,b) | 中 | 需匹配格式 | 旧代码维护 |
换问法:若题目问 ">>> '-'.join('abc')" 的结果是什么?——答案是 "'a-b-c'",因为字符串本身也是可迭代对象,迭代结果是单个字符。
【自测】 以下代码的输出是什么?
items = [1, 2, 3]
try:
result = ",".join(items)
except Exception as e:
print(type(e).__name__)答:输出 "TypeError"。join 要求可迭代对象中的元素必须是字符串,整数不能直接与字符串连接,需先通过 map(str, items) 转换。与第 P37 题连考。
【知识关联】
- 同库关联:与 P08/P20;
sep.join(iterable)要求元素是 str。 - 实现层:高效一次分配。
- 面试追问:① join 数字列表会怎样?② 与循环 += 性能?
【拓展延伸】
- 变式问法:
",".join(["a","b"]);join 生成器。 - 版本差异:语义稳定。
- 工程注意点:路径用 os.path.join/pathlib;SQL 勿手拼。
P37 · 知识点:split
【题目】"a,b,c".split(",") 的结果是?
A. ('a', 'b', 'c') B. 'a b c' C. ['a,b,c'] D. ['a', 'b', 'c']
答案:D
【考点】split 按分隔符拆分为列表,与 join 互逆。
【结论】选 D。split() 方法按指定分隔符将字符串拆分为列表。
【推导过程】 "a,b,c".split(",") 的执行过程:
- 以 "," 为分隔符扫描字符串
- 在逗号处将字符串切分为三段:"a"、"b"、"c"
- 将三段字符串放入列表中
- 返回列表 ['a', 'b', 'c']
【逐项辨析】 D. 正确。split(",") 返回由拆分结果组成的列表 ['a', 'b', 'c']。 B. 错误。'a b c' 是字符串,但 split 返回的是列表而非字符串。 C. 错误。['a,b,c'] 是未找到分隔符时的结果(或仅当字符串中无分隔符时)。 A. 错误。split 返回的是列表 list,不是元组 tuple。
【知识点】 str.split(sep=None, maxsplit=-1) 是字符串处理的核心方法:
- 功能:按分隔符将字符串拆分为列表
- sep 参数:
- 指定分隔符:如 split(",") 按逗号拆分
- 不指定(None):按任意空白字符拆分,且自动去除空字符串
- maxsplit 参数:限制最大拆分次数,如 "a,b,c".split(",", 1) → ['a', 'b,c']
- 返回值:始终返回列表(list),即使只有一个元素也返回单元素列表
split() 与 join() 的互逆性: s = "a,b,c" lst = s.split(",") # ['a', 'b', 'c'] s2 = ",".join(lst) # "a,b,c" assert s == s2
相关方法:
- rsplit():从右侧开始拆分
- splitlines():按行边界拆分
【记忆锚点】 “split 一刀切,列表装起来;join 再缝上,字符串归来”——split 和 join 互为逆操作。
【易混对比】
| 方法 | 返回值类型 | 默认分隔行为 | 空字符串处理 | 示例 "a,,b".split(",") |
|---|---|---|---|---|
| split(",") | 列表 | 按指定字符 | 保留空串 | ['a', '', 'b'] |
| split() | 列表 | 按任意空白 | 自动去空串 | N/A(不传参时不同) |
| rsplit(",", 1) | 列表 | 从右侧拆分 | 保留空串 | ['a,', 'b'] |
| partition(",") | 元组 | 只拆一次 | 保留空串 | ('a', ',', ',b') |
换问法:若题目问 ">>> ' a b '.split()" 的结果是什么?——答案是 ['a', 'b'],因为不传参数时按任意空白拆分且自动合并连续空白。
【自测】 以下代码的输出是什么?
s = "one:two:three"
print(s.split(":", 1))
print(s.rsplit(":", 1))答:第一行输出 ['one', 'two:three'](从左拆 1 次),第二行输出 ['one:two', 'three'](从右拆 1 次)。maxsplit=1 限制只拆一次,rsplit 从右侧开始。与第 P38 题连考。
【知识关联】
- 同库关联:与 P20;split/rsplit/splitlines。
- 实现层:不给 sep 按空白;给出 sep 精确切。
- 面试追问:①
"a,b,,c".split(",")?② maxsplit?
【拓展延伸】
- 变式问法:
" a b ".split()去首尾空白。 - 版本差异:语义稳定。
- 工程注意点:日志分割注意空段;大文件逐行而不是一次 split。
P38 · 知识点:find 与 index
【题目】s = "hello",s.find("l") 和 s.index("l") 的结果分别是?
A. 2 和 2 B. -1 和抛 ValueError C. 2 和抛 ValueError D. 3 和 3
答案:A
【考点】find 找不到返回 -1;index 找不到抛异常;都返回首个匹配索引。
【结论】选 A。find() 和 index() 在找到子串时都返回首次匹配的索引位置。
【推导过程】 s = "hello",s.find("l") 和 s.index("l") 的执行过程:
- 字符串 "hello" 的索引:h(0), e(1), l(2), l(3), o(4)
- 两个方法都从左侧开始查找字符 "l"
- 首个 "l" 出现在索引 2 的位置
- find("l") 返回 2,index("l") 返回 2
【逐项辨析】 A. 正确。首个 'l' 的索引为 2,find 和 index 都返回 2。 B. 错误。find("l") 找到了匹配项,返回 2,不是 -1。 C. 错误。index("l") 找到了匹配项,返回 2,不会抛 ValueError。 D. 错误。3 是第二个 'l' 的索引,两个方法都返回首个匹配位置。
【知识点】 str.find(sub[, start[, end]]) 和 str.index(sub[, start[, end]]) 都用于查找子串:
- 相同点:
- 都从左往右查找子串首次出现的位置
- 都支持 start 和 end 参数限定搜索范围
- 找到时返回子串的首字符索引
- 不同点(关键差异):
- find() 找不到时返回 -1,不会抛异常(安全)
- index() 找不到时抛出 ValueError(严格)
类似方法对:
- rfind() / rindex():从右侧开始查找
- count():统计子串出现次数
使用建议:
- 不确定子串是否存在时,优先使用 find() 或先用 in 判断
- 需要程序在子串不存在时中断执行,可使用 index()
【记忆锚点】 “find 找不到回 -1,index 找不到就翻脸”——find 容错返回 -1,index 严格抛异常。
【易混对比】
| 方法 | 查找方向 | 找到时返回值 | 找不到时行为 | 安全性 | 适用场景 |
|---|---|---|---|---|---|
| find() | 从左 | 首个匹配索引 | 返回 -1 | 高 | 不确定是否存在 |
| index() | 从左 | 首个匹配索引 | 抛 ValueError | 低 | 确信一定存在 |
| rfind() | 从右 | 末个匹配索引 | 返回 -1 | 高 | 查找最后出现 |
| rindex() | 从右 | 末个匹配索引 | 抛 ValueError | 低 | 查找最后出现 |
| count() | 全局 | 出现次数 | 返回 0 | 高 | 统计出现次数 |
换问法:若题目问 ">>> 'hello'.find('z')" 的结果是什么?——答案是 -1,因为 'z' 不在字符串中,find 找不到时返回 -1 而非抛异常。
【自测】 以下代码的输出是什么?
s = "banana"
print(s.find("na"))
print(s.rfind("na"))答:第一行输出 2("na" 首次出现在索引 2),第二行输出 4("na" 最后一次出现在索引 4)。find 找首次,rfind 找末次。与第 P39 题连考。
【知识关联】
- 同库关联:与 P33;find 返回 -1,index 抛异常。
- 实现层:子串搜索;rfind/rindex。
- 面试追问:① 未找到时二者行为?② 用 in 更好?
【拓展延伸】
- 变式问法:
"abc".find("x")为 -1;index 抛 ValueError。 - 版本差异:语义稳定。
- 工程注意点:判断存在用 in;需要位置再 find/index。
P39 · 知识点:f-string
【题目】name = "Tom",执行 f"{name}" 的结果是?
A. "Tom" B. "name" C. "{name}" D. 抛异常
答案:A
【考点】f-string(格式化字符串字面量,Python 3.6+)。
【结论】选 A。f-string 会在花括号内对表达式求值,并将结果插入字符串中。
【推导过程】 name = "Tom",执行 f"{name}" 的过程:
- 前缀 f 表明这是一个格式化字符串字面量
- 花括号 {name} 中的 name 是一个变量名
- 解释器对 name 求值,得到字符串 "Tom"
- 将 "Tom" 插入到对应位置,最终结果为 "Tom"
【逐项辨析】 A. 正确。f-string 对 {name} 求值,name 的值为 "Tom",因此结果为 "Tom"。 B. 错误。"name" 是字符串字面量,只有花括号内的表达式被求值并替换。 C. 错误。"{name}" 是普通字符串(无前缀 f)的输出结果。 D. 错误。name 已定义且为字符串类型,f-string 求值不会抛异常。
【知识点】 f-string(格式化字符串字面量,Formatted String Literals)是 Python 3.6+ 引入的字符串格式化方式:
- 语法:在字符串前加 f 或 F 前缀,如 f"Hello {name}"
- 求值规则:花括号 {} 内的表达式会被实时求值并转换为字符串插入
- 支持内容:
- 变量:f"{x}"
- 表达式:f"{x + y}"
- 函数调用:f"{len(s)}"
- 字典/列表访问:f"{d['key']}"
- 格式化规范:f"{pi:.2f}"(保留两位小数)
- 性能:f-string 在运行时求值,通常比 % 格式化和 str.format() 更快
与普通字符串的区别:
- 普通字符串 "..." 中的 {name} 就是字面文本
- f-string f"..." 中的 {name} 会被求值替换
【记忆锚点】 “f 前缀一点,花括号一算,变量往里钻”——f-string 的核心就是前缀 f 加花括号表达式。
【易混对比】
| 格式化方式 | 语法示例 | Python 版本 | 可读性 | 性能 | 特点 |
|---|---|---|---|---|---|
| f-string | f"{name}" | 3.6+ | 高 | 最快 | 简洁直观 |
| str.format() | "{}".format(name) | 2.6+ | 中 | 中等 | 功能丰富 |
| % 格式化 | "%s" % name | 全版本 | 低 | 较慢 | 类 C 风格 |
| 模板字符串 | Template("$name") | 2.4+ | 高 | 较慢 | 安全性高 |
换问法:若题目问 ">>> f'{2 + 3 * 4}'" 的结果是什么?——答案是 '14',因为花括号内支持完整表达式求值。
【自测】 以下代码的输出是什么?
x = 3.14159
print(f"pi = {x:.2f}")
print(f"2^10 = {2 ** 10}")答:第一行输出 "pi = 3.14"(保留两位小数),第二行输出 "2^10 = 1024"(花括号内支持表达式求值)。f-string 的格式化语法非常强大。与第 P40 题连考。
【知识关联】
- 同库关联:与 P08/P10;与 Java MessageFormat/String.format 对照。
- 实现层:f-string 编译期生成,比 % 和 format 快;可嵌表达式。
- 面试追问:① f-string 能否调试
=?② 与 format 选择?
【拓展延伸】
- 变式问法:
f"{x=}";格式说明符:.2f。 - 版本差异:3.6 引入;3.8 支持
=;3.12 改进错误提示。 - 工程注意点:复杂格式保持可读;i18n 场景用 format 便于翻译。
P40 · 知识点:字符串判断方法
【题目】判断一个 ASCII 数字串(如 "123")是否全部由数字字符组成,可以使用?
A. isdigit() B. isnumeric() C. isalpha() D. A 和 B 都可以
答案:D
【考点】isdigit()/isnumeric()/isdecimal()/isalpha() 的判断范围。
【结论】选 D。对于纯 ASCII 数字串(如 "123"),isdigit() 和 isnumeric() 都返回 True。
【逐项辨析】 A. 不完全正确。虽然 "123".isdigit() 返回 True,但 B 选项同样正确,单独选 A 不全面。 B. 不完全正确。虽然 "123".isnumeric() 返回 True,但 A 选项同样正确,单独选 B 不全面。 C. 错误。isalpha() 判断字符串是否全部由字母组成,"123".isalpha() 返回 False。 D. 正确。对于纯 ASCII 数字串,isdigit() 和 isnumeric() 都返回 True,因此两者都可以使用。
【知识点】 Python 提供了多个字符串判断方法,用于检测字符串的字符组成:
- isdigit():判断字符串是否全部由数字字符组成
- 包含:0-9、上标数字(如 ²)等
- 不包含:中文数字、罗马数字、分数等
- isnumeric():判断字符串是否全部由数字类字符组成
- 包含:0-9、中文数字(一二三)、罗马数字(Ⅳ)、分数(½)等
- 判定范围最广
- isdecimal():判断字符串是否全部由十进制数字字符组成
- 仅包含:0-9
- 判定范围最严格
- isalpha():判断字符串是否全部由字母组成
- 包含:中英文字母等
- 数字、空格、标点均返回 False
判定范围关系:isdecimal() ⊆ isdigit() ⊆ isnumeric()
对于纯 ASCII 数字串(如 "123"),三者均返回 True。但当涉及特殊数字字符时:
- "½".isnumeric() → True
- "½".isdigit() → False
- "½".isdecimal() → False
【记忆锚点】 “decimal 最死板,digit 稍宽泛,numeric 最博爱”——判定范围从小到大依次是 isdecimal、isdigit、isnumeric。
【易混对比】
| 方法 | 判定范围 | "123" | "²" | “一二三” | "½" | "abc" |
|---|---|---|---|---|---|---|
| isdecimal() | 仅十进制数字 | True | False | False | False | False |
| isdigit() | 数字字符 | True | True | False | False | False |
| isnumeric() | 数字类字符 | True | True | True | True | False |
| isalpha() | 字母字符 | False | False | True(实测 '一二三'.isalpha() 为 True,中文汉字算字母) | False | True |
换问法:若题目改为 “判断 '½' 是否由数字字符组成,应使用哪个方法?”——答案是 isnumeric(),因为 isdigit() 和 isdecimal() 对 "½" 都返回 False。
【自测】 以下代码的输出分别是什么?
print("Ⅷ".isdigit())
print("Ⅷ".isnumeric())
print("42.5".isdigit())答:第一行输出 False(罗马数字 8 不被 isdigit 认可),第二行输出 True(罗马数字属于 numeric),第三行输出 False(小数点 "." 不是数字字符,因此整个字符串返回 False)。与第 P33 题连考。
【知识关联】
- 同库关联:与 P33–P39 字符串方法群。
- 实现层:isdigit/startswith 等为便捷判断。
- 面试追问:①
"²".isdigit()与 isnumeric?② 判断中文?
【拓展延伸】
- 变式问法:
"abc123".isalnum();startswith 元组。 - 版本差异:语义稳定。
- 工程注意点:校验用正则更严谨;注意 Unicode 类别。