字符串操作:索引、切片、常用方法、格式化
一句话概述
字符串是 Python 中最常用的数据类型之一——从用户交互的 print/input,到文件读写的内容,到 AI 模型中的文本数据,处处都有字符串的身影。字符串本质上是不可变的 Unicode 字符序列,支持索引(通过位置访问单个字符)、切片(提取子串)、丰富的内置方法(大小写转换、查找替换、拆分连接、判断类型),以及强大的格式化语法(f-string、format、%)。掌握字符串操作,是处理一切文本数据的基础,也是 NLP(自然语言处理)入门的必修课。
💡 核心要点:①字符串是不可变序列,用单引号、双引号或三引号创建 ②索引从 0 开始,负数索引从 -1 倒着数,切片语法[start:end:step]提取子串 ③常用方法分四类:大小写转换、查找替换、拆分连接、判断类型 ④f-string 是目前最推荐的格式化方式,f"{变量:格式}"简洁强大 ⑤转义字符\n(换行)\t(制表)\\(反斜杠)用于表示特殊字符
教学与演示
一、字符串的索引与切片——像操作列表一样操作文本
是什么:字符串是字符的有序序列,和列表一样支持索引(s[i])和切片(s[start:end:step])。索引从 0 开始,负数索引从 -1(倒数第一个)开始。切片返回子字符串(左闭右开)。但字符串和列表有一个关键区别——字符串是不可变的,s[0] = 'X' 会报错,想修改只能创建新字符串。
大白话 把字符串想象成一串珍珠项链——每颗珍珠是一个字符,你可以数"第3颗是什么"(索引),也可以剪下一段(切片),但不能单独替换一颗珍珠(不可变)。想换珍珠?只能把整条项链重做(创建新字符串)。这个"不可变"的设计其实很聪明——确保字符串在任何地方都安全可靠,不用担心被意外篡改。
为什么:索引和切片是字符串操作的基本功。解析文件路径时提取扩展名(path[-4:])、处理 DNA 序列时截取基因片段(dna[100:200])、字符串反转(s[::-1])——这些需求无处不在。理解索引和切片让你能用最简洁的代码完成复杂的文本截取任务。
怎么做:
import numpy as np
# ====== 1. 字符串索引——像数组一样访问字符 ======
text = "Python编程入门"
# 正索引: 0 1 2 3 4 5 6 7 8 9
# P y t h o n 编 程 入 门
# 负索引: -10 -9 -8 -7 -6 -5 -4 -3 -2 -1
print("字符串:", repr(text)) # 'Python编程入门'
print("长度:", len(text)) # 10
print("\n=== 正索引 ===")
print(f"text[0] = '{text[0]}'") # 'P' — 第一个字符
print(f"text[5] = '{text[5]}'") # 'n' — 第六个字符
print(f"text[6] = '{text[6]}'") # '编' — 中文字符也占一个位置
print("\n=== 负索引 ===")
print(f"text[-1] = '{text[-1]}'") # '门' — 倒数第一个
print(f"text[-2] = '{text[-2]}'") # '入' — 倒数第二个
print(f"text[-3] = '{text[-3]}'") # '程' — 倒数第三个
# ====== 2. 切片——提取子字符串 ======
# 语法:text[start:end:step],start 包含,end 不包含(左闭右开)
print("\n=== 切片 ===")
print(f"text[0:6] = '{text[0:6]}'") # 'Python' — 索引 0~5
print(f"text[:6] = '{text[:6]}'") # 'Python' — 省略 start 默认从 0 开始
print(f"text[6:] = '{text[6:]}'") # '编程入门' — 省略 end 默认到末尾
print(f"text[:] = '{text[:]}'") # 完整拷贝
# 步长切片
print(f"text[::2] = '{text[::2]}'") # 'Pto编入' — 隔一个取一个
# 反转字符串(经典技巧!)
print(f"text[::-1] = '{text[::-1]}'") # '门入程编nohtyP' — 反转!
# ====== 3. 实用切片场景 ======
# 提取文件扩展名
filename = "document.pdf"
dot_pos = filename.rfind('.') # 找最后一个 . 的位置
ext = filename[dot_pos:] # 从 . 开始切片
print(f"\n文件名: {filename}, 扩展名: '{ext}'")
# 提取 URL 的域名部分
url = "https://www.example.com/page?id=123"
# 去掉协议 https://
domain_start = url.find("://") + 3 # "://" 后 3 个位置
after_protocol = url[domain_start:] # "www.example.com/page?id=123"
# 截取到第一个 /
slash_pos = after_protocol.find("/")
domain = after_protocol[:slash_pos] if slash_pos != -1 else after_protocol
print(f"URL: {url}")
print(f"域名: {domain}") # www.example.com
# ====== 4. 字符串的不可变性 ======
s = "hello"
print(f"\n原始: '{s}'")
# s[0] = 'H' ❌ TypeError: 'str' object does not support item assignment
# 正确做法:创建新字符串
s = 'H' + s[1:] # H + ello = Hello
print(f"修改后: '{s}'") # 'Hello'
# ====== 5. 遍历字符串 ======
text = "AI全栈"
print(f"\n遍历 '{text}':")
for i, ch in enumerate(text): # enumerate 同时获取索引和字符
print(f" 索引 {i}: '{ch}' (Unicode: {ord(ch)})")什么用:在 AI 文本处理中,索引和切片是高频操作。NLP 中提取子词(subword)序列:token[i:i+3];数据预处理中截断过长文本:text[:max_len];路径处理中提取目录和文件名;文本增强中反转文本做数据扩充:augmented = text[::-1]。切片语法和 numpy/PyTorch 的数组切片一脉相承。
二、常用方法——四大类文本处理工具
是什么:Python 字符串自带 40+ 个内置方法,分为四大类:①大小写转换(upper、lower、title、capitalize);②查找替换(find、index、replace、count);③拆分连接(split、join、strip、partition);④判断类型(isdigit、isalpha、isalnum、startswith、endswith)。这些方法都不修改原字符串(不可变),而是返回新字符串。
大白话 字符串方法就像一个文字处理工具箱。upper()是"全大写"按钮(HELLO),strip()是"去两端空格"橡皮擦,split()是"按逗号切菜"的刀,join()是把切好的菜重新串起来。每个工具专注做一件事,组合起来能解决所有文本处理问题。
为什么:真实世界的文本数据是"脏"的——有多余空格、大小写不统一、包含特殊字符、格式各异。字符串方法就是清洗和标准化文本的核心工具。在数据预处理中,你几乎总要先做一轮 strip().lower().replace() 操作,才把文本喂给后续流程。
怎么做:
import numpy as np
# ====== 1. 大小写转换 ======
s = " Hello, AI World! "
print("原始字符串:", repr(s))
print("\n=== 大小写转换 ===")
print(f"upper() : '{s.upper()}'") # ' HELLO, AI WORLD! '
print(f"lower() : '{s.lower()}'") # ' hello, ai world! '
print(f"title() : '{s.title()}'") # ' Hello, Ai World! '
print(f"capitalize(): '{s.capitalize()}'") # 仅首字符大写
# AI 数据预处理:统一小写用于词表
texts = ["Hello World", "HELLO world", "hello WORLD"]
normalized = [t.lower() for t in texts] # 全部转为小写
print(f"\n统一小写: {normalized}") # ['hello world', 'hello world', 'hello world']
# ====== 2. 查找与替换 ======
text = "Python is easy. Python is powerful."
print(f"\n原始文本: '{text}'")
# find():查找子串位置,找不到返回 -1
print(f"find('Python'): {text.find('Python')}") # 0
print(f"find('Python',5):{text.find('Python', 5)}") # 18 — 从索引5开始
print(f"find('Java'): {text.find('Java')}") # -1 — 没找到
# count():统计出现次数
print(f"count('is'): {text.count('is')}") # 2
# replace():替换(不修改原字符串!)
replaced = text.replace("Python", "Java") # 全部替换
print(f"replace 全部: '{replaced}'")
replaced2 = text.replace("Python", "Java", 1) # 只替换 1 次
print(f"replace 1次: '{replaced2}'")
# ====== 3. 拆分与连接(最常用!) ======
# split():按分隔符拆成列表
csv_line = "张三,25,北京,工程师"
fields = csv_line.split(",") # 按逗号拆分
print(f"\nsplit(','): {fields}") # ['张三', '25', '北京', '工程师']
# 按空格拆分
sentence = "Python is awesome"
words = sentence.split() # 默认按任意空白字符拆分
print(f"split(): {words}") # ['Python', 'is', 'awesome']
# rsplit():从右边开始拆分(限制拆分次数)
path = "/home/user/documents/file.txt"
parts = path.rsplit("/", 1) # 从右边拆 1 次
print(f"rsplit('/', 1): {parts}") # ['/home/user/documents', 'file.txt']
# join():用分隔符连接列表的字符串元素
words = ["Python", "is", "fun"]
joined = " ".join(words) # 空格连接
print(f"\n' '.join(): '{joined}'") # 'Python is fun'
joined2 = " → ".join(words)
print(f"' → '.join(): '{joined2}'") # 'Python → is → fun'
# ====== 4. 去除空白与填充 ======
s = " \t Hello World! \n " # 含各种空白字符
print(f"\n原始: {repr(s)}")
print(f"strip(): {repr(s.strip())}") # 'Hello World!'
print(f"lstrip(): {repr(s.lstrip())}") # 去左边
print(f"rstrip(): {repr(s.rstrip())}") # 去右边
# strip() 可以指定要去除的字符
code = "###Python###"
print(f"strip('#'): '{code.strip('#')}'") # 'Python'
# center/ljust/rjust:填充对齐
name = "AI"
print(f"center(10): '{name.center(10, '*')}'") # '****AI****'
print(f"ljust(10): '{name.ljust(10, '-')}'") # 'AI--------'
print(f"zfill(5): '{'42'.zfill(5)}'") # '00042'
# ====== 5. 判断类型 ======
print(f"\n=== 类型判断 ===")
tests = ["123", "abc", "abc123", " ", "3.14"]
for s_test in tests:
print(f" '{s_test}': isdigit={s_test.isdigit()}, "
f"isalpha={s_test.isalpha()}, isalnum={s_test.isalnum()}")
# startswith / endswith:检查前缀和后缀
filename = "data_2024.csv"
print(f"\nstartswith('data'): {filename.startswith('data')}") # True
print(f"endswith('.csv'): {filename.endswith('.csv')}") # True什么用:在 AI 数据预处理流水线中,字符串方法占据了半壁江山。文本清洗:text.strip().lower() 去掉噪音和统一格式;分词前处理:.split() 将句子拆成词列表;特征工程:.startswith('http') 判断是否为 URL;数据验证:.isdigit() 检查输入是否为数字。NLP 中几乎每个 pipeline 的第一步都是这些方法。
三、字符串格式化——三种写法,一种推荐
是什么:字符串格式化让你把变量的值插入到字符串模板中,生成最终的字符串。Python 有三种方式:①f-string(f"...{expr}...",Python 3.6+,最推荐);②format() 方法("...{}...".format(var),Python 2.6+);③**% 格式化**("...%s..." % var,老式风格)。三种方式都能实现变量插值和格式控制,但 f-string 最简洁直观。
大白话 字符串格式化就像填表格——你有一个模板,模板里留了空(占位符),你把数据填进去就得到完整的结果。f"{name}今年{age}岁" 就像填空题:"____今年____岁",把 name 和 age 分别填到横线处。f-string 是目前最方便的写法——直接在字符串里写变量名,Python 自动帮你替换。
为什么:程序中几乎每行 print、每条日志、每个 API 响应都需要字符串格式化。f-string 之所以被推崇,是因为它把"什么是模板"和"填什么数据"写在一起,不离散——f"Epoch {epoch}: loss={loss:.4f}" 一目了然。此外 f-string 比 % 格式化和 format() 都快(编译时优化)。
怎么做:
import numpy as np
# ====== 1. 三种格式化方式的对比 ======
name = "小明"
age = 18
score = 95.5
# 方式1:f-string(Python 3.6+,最推荐!)
s1 = f"{name}今年{age}岁,考了{score}分"
print("f-string:", s1)
# 方式2:format() 方法
s2 = "{}今年{}岁,考了{}分".format(name, age, score)
print("format():", s2)
# 方式3:% 格式化(老式,了解即可)
s3 = "%s今年%d岁,考了%.1f分" % (name, age, score)
print("% 格式化:", s3)
# ====== 2. f-string 可以放任意表达式 ======
# 可以在花括号里写计算
a, b = 10, 3
print(f"\n{a} + {b} = {a + b}") # 10 + 3 = 13
# 可以调用函数
print(f"大写: {'hello'.upper()}") # HELLO
print(f"长度: {len('hello')}") # 5
# 可以使用条件表达式(三元)
temp = 30
print(f"今天{'热' if temp > 28 else '凉快'}") # 热
# ====== 3. f-string 的格式控制 ======
pi = 3.141592653589793
print("\n=== 数字格式化 ===")
print(f"π = {pi:.2f}") # 保留 2 位小数 → 3.14
print(f"π = {pi:.4f}") # 保留 4 位小数 → 3.1416
# 百分比
rate = 0.952
print(f"准确率: {rate:.1%}") # 95.2%
# 千分位
big_num = 1234567890
print(f"千分位: {big_num:,}") # 1,234,567,890
# 整数进制
n = 255
print(f"二进制={n:b}, 十六进制={n:x}") # 11111111, ff
# ====== 4. 对齐与填充 ======
print("\n=== 对齐与填充 ===")
name = "AI"
print(f"左对齐: |{name:<10}|") # |AI |
print(f"右对齐: |{name:>10}|") # | AI|
print(f"居中对齐: |{name:^10}|") # | AI |
print(f"居中填充*: |{name:*^10}|") # |****AI****|
# ====== 5. AI 实战:训练日志格式化 ======
epochs = [1, 2, 3, 4, 5]
losses = [0.8567, 0.6234, 0.4512, 0.3201, 0.2543]
accs = [0.612, 0.735, 0.812, 0.875, 0.912]
print("\n=== 训练日志 ===")
print(f"{'Epoch':<8}{'Loss':<12}{'Accuracy':<10}") # 表头
print("-" * 30)
for e, l, a in zip(epochs, losses, accs):
print(f"{e:<8}{l:<12.4f}{a:<10.2%}") # 对齐输出什么用:在 AI 开发中,f-string 几乎出现在每行日志打印中。训练循环:print(f"Epoch {epoch}/{total}: loss={loss:.4f}, acc={accuracy:.2%}");模型评估:print(f"Precision: {prec:.3f}, Recall: {rec:.3f}, F1: {f1:.3f}");调试信息:print(f"Input shape: {x.shape}, dtype: {x.dtype}")。格式化的对齐功能在生成表格化输出(如模型对比、实验结果汇总)时非常实用。
四、转义字符与原始字符串——处理特殊字符
是什么:转义字符是以反斜杠 \ 开头的特殊字符序列,用于表示无法直接输入或有特殊含义的字符。常用转义字符有:\n(换行)、\t(制表符)、\\(反斜杠本身)、\'(单引号)、\"(双引号)。原始字符串(raw string)在字符串前加 r,会忽略转义——反斜杠就是反斜杠,常用于正则表达式和文件路径。
大白话 转义字符就像键盘上的"Fn"组合键——单独按一个键是一个意思,配合 Fn 就是另一个意思。\n不是"反斜杠加 n 两个字符",而是"换行"这一个控制字符。原始字符串r"...\"就像关闭了 Fn 键——所有字符都是字面意思。在处理 Windows 文件路径(C:\Users\name)时,原始字符串能救你于水火——不用把每个\写成\\。
为什么:转义字符是文本处理的必备知识。格式化输出的对齐靠 \t,多行日志靠 \n,文件路径处理(尤其是 Windows)靠原始字符串,正则表达式中的反斜杠地狱也靠原始字符串解决。不理解转义,你会在路径处理和正则表达式上踩很多坑。
怎么做:
import numpy as np
# ====== 1. 常用转义字符 ======
print("=== 常用转义字符 ===")
print("换行符 \\n:") # 先打印标签
print("第一行\n第二行\n第三行") # \n 产生换行
print()
print("制表符 \\t:") # 标签
print("姓名\t年龄\t城市") # \t 产生制表对齐
print("张三\t25\t北京")
print("李四\t30\t上海")
print()
# 引号转义
print("反斜杠 \\\\") # 打印一个反斜杠
print('单引号: \'包含单引号\'') # 单引号内嵌单引号
print("双引号: \"包含双引号\"") # 双引号内嵌双引号
# ====== 2. 原始字符串 r"..."——反斜杠就是反斜杠 ======
# 普通字符串中的 \n 被解析为换行
normal = "C:\\Users\\name\\documents" # 每个 \ 都要写成 \\
print(f"\n普通字符串路径: {normal}")
# 原始字符串中的 \n 就是 \ 和 n 两个字符
raw = r"C:\Users\name\documents" # 不需要双重反斜杠!
print(f"原始字符串路径: {raw}")
# ⚠️ 原始字符串不能以单个反斜杠结尾
# raw_end = r"C:\path\" ❌ 语法错误!
raw_end = r"C:\path\\" # 需要双反斜杠结尾
print(f"原始字符串结尾: {raw_end}")
# ====== 3. 原始字符串在正则表达式中的应用 ======
import re
# 正则中 \d 表示数字,\w 表示字母
# 普通字符串中需要写 \\d(双重转义)
pattern_normal = "\\d{3}-\\d{4}" # 匹配 3位-4位数字
# 原始字符串中直接写 \d
pattern_raw = r"\d{3}-\d{4}" # 与上面等效,但更清晰!
text = "电话: 010-1234, 021-5678"
matches_normal = re.findall(pattern_normal, text)
matches_raw = re.findall(pattern_raw, text)
print(f"\n正则匹配(普通): {matches_normal}") # ['010-1234', '021-5678']
print(f"正则匹配(原始): {matches_raw}") # ['010-1234', '021-5678']
# ====== 4. AI 实战:文本数据清洗 ======
# 模拟:爬虫抓取到的原始文本(含各种转义字符和空白)
raw_text = " \t 机器学习\\n是AI的核心分支。\n深度学习\\n是其中最重要的技术。 \n "
print(f"\n=== 文本清洗 ===")
print(f"原始文本: {repr(raw_text)}")
# 清洗流水线:去空白 → 统一换行符 → 标准化
cleaned = raw_text.strip() # 1. 去除两端空白
cleaned = cleaned.replace("\\n", " ") # 2. 把字面的 \n 替换为空格
cleaned = cleaned.replace("\n", " ") # 3. 把真正的换行也替换为空格
cleaned = cleaned.replace("\t", " ") # 4. 把制表符替换为空格
# 5. 把多个连续空格合并为一个
import re
cleaned = re.sub(r'\s+', ' ', cleaned) # 正则:多个空白 → 一个空格
print(f"清洗后: '{cleaned}'")
# ====== 5. 多行字符串与 docstring ======
# 三引号写多行文本(自动保留换行)
multi = """这是一段
多行文本,
换行被自动保留。"""
print(f"\n多行文本: {repr(multi)}")
# docstring:函数的文档说明(也是三引号字符串)
def preprocess_text(text, max_length=100):
"""对文本进行标准的 NLP 预处理。
处理流程:
1. 转为小写
2. 去除多余空白
3. 截断到指定长度
Args:
text: 原始文本
max_length: 最大保留长度
Returns:
处理后的文本
"""
text = text.lower().strip()
return text[:max_length]
# 可以通过 .__doc__ 访问 docstring
print(f"函数文档: {preprocess_text.__doc__[:80]}...")什么用:在 AI 的数据工程中,转义字符和原始字符串是日常工具。爬虫抓取的文本常含 \n、\t、 等需要清理;正则表达式几乎总是用原始字符串(r"\d+" 比 "\\d+" 清晰);跨平台的文件路径处理用原始字符串避免反斜杠问题;docstring 用三引号写函数文档,是 Python 代码规范的一部分。
概念关系图谱
| 概念 | 核心含义 | 与AI的关系 | 关联概念 |
|---|---|---|---|
| str | 不可变的Unicode字符序列 | 文本数据、NLP输入、文件内容 | list、tuple |
| 索引 | 通过整数位置访问字符 | 逐字分析、位置编码 | 切片、下标 |
| 切片 | 提取子字符串 | 文本截断、子词提取 | 索引、步长 |
| split/join | 拆分字符串为列表 / 连接列表为字符串 | 分词、词表构建 | 列表、分隔符 |
| strip | 去除字符串两端指定字符 | 数据清洗、格式标准化 | lower、replace |
| f-string | 内嵌表达式的格式化字符串 | 训练日志、结果输出 | format()、%格式化 |
| 转义字符 | \n、\t等特殊字符 | 文本清洗、正则表达式 | 原始字符串 |
| 不可变 | 创建后不能修改字符 | 安全性、哈希键 | tuple、frozenset |
重点答疑
Q1: 字符串的"不可变"到底是什么意思?为什么设计成这样?
不可变意味着字符串对象一旦创建,其内部字符序列就不能更改。s = "hello"; s = "world" 不是修改了原字符串——而是创建了新字符串 "world",把变量 s 指向了它,原来的 "hello" 被丢弃(或被垃圾回收)。设计成不可变的好处:①安全——字符串可以作为字典的键(需要不可变);②性能——Python 可以缓存/复用相同字符串(intern),节省内存;③线程安全——不可变对象天然防并发修改。唯一的"代价"是频繁拼接字符串时会产生临时对象,但通常不重要,极端场景用 join() 替代 +。
Q2: split() 和 split(' ') 有什么区别?
split()(不带参数)按任意连续空白字符拆分(空格、制表符 \t、换行 \n 等),多个空白字符被视为一个分隔符,且自动去除首尾空白。split(' ')(空格参数)按单个空格严格拆分——连续两个空格会产生一个空字符串元素。举例:"a b".split() → ['a', 'b'](两个连续空格被视为一个),而 "a b".split(' ') → ['a', '', 'b'](两个空格产生一个空字符串)。一般数据清洗用默认的 split(),精确解析(如 CSV)用指定的分隔符。
Q3: f-string 和 format() 哪个更好?为什么推荐 f-string?
f-string 是 Python 3.6 引入的,在绝大多数场景下优于 format()。原因:①可读性——变量直接内嵌在字符串中,不需要跳到最后看 .format() 的参数列表;②性能——f-string 在编译时解析,比 format() 运行时解析快 10-20%;③表达能力——花括号内可以写任意表达式(计算、函数调用、三元运算),format() 只能放变量名。唯一用 format() 的场景:格式化模板需要从外部动态加载或需要延迟格式化,因为 format() 可以分开定义模板和数据。
Q4: 原始字符串 r"..." 有什么限制?能用 r"\" 结尾吗?
原始字符串中,反斜杠仍然是引号转义符的一部分——用于转义引号字符本身。这意味着:① r"\" 会报错——因为 \" 被当作转义引号,导致字符串没有正确的结束引号;②原始字符串不能以奇数个反斜杠结尾,因为最后一个反斜杠会转义引号;③如果需要结尾反斜杠,要么写成 r"\\"(两个反斜杠),要么不用原始字符串写成 "\\"。在实践中这些限制很少碰到——文件路径通常不以反斜杠结尾。
Q5: 字符串拼接用 + 还是 join()?
对于少量字符串拼接(2-3 个),用 + 更方便——"Hello " + name 简洁直观。对于大量字符串拼接(如循环中逐词拼接),必须用 join()!因为字符串不可变,每次 + 都会创建新字符串对象并复制所有内容——1000 次 + 会产生 1000 个中间临时字符串,极其低效(O(n²))。join() 预先计算总长度,一次性分配内存,O(n) 完成。Python 的 CPython 实现对少量 + 做了优化,但大数据量时 join() 仍然是唯一正确选择。
章节单词汇总
| 英文 | 音标 | 术语/释义 |
|---|---|---|
| string | /strɪŋ/ | 字符串;不可变的Unicode字符序列 |
| index | /ˈɪndeks/ | 索引;通过位置访问字符 |
| slice | /slaɪs/ | 切片;提取子字符串 |
| concatenation | /kənˌkætəˈneɪʃən/ | 拼接;把字符串连在一起 |
| format | /ˈfɔːrmæt/ | 格式化;把变量值插入字符串模板 |
| escape | /ɪˈskeɪp/ | 转义;用反斜杠表示特殊字符 |
| whitespace | /ˈwaɪtspeɪs/ | 空白字符;空格、制表符、换行等 |
| literal | /ˈlɪtərəl/ | 字面量;代码中直接写的值 |
面试练习
Q1 [单选] "Python"[1:4] 的结果是什么?
- A.
"Pyt" - B.
"yth" - C.
"ytho" - D.
"Py"
解答:B 正确。索引从 0 开始:P=0, y=1, t=2, h=3, o=4, n=5。[1:4] 取索引 1、2、3 → "yth"。左闭右开,不包含索引 4。
Q2 [单选] s = "Hello"; s[0] = "h"; print(s) 输出什么?
- A.
"hello" - B.
"Hello" - C. 抛出 TypeError
- D.
"hEllo"
解答:C 正确。字符串是不可变的,s[0] = "h"会抛出TypeError: 'str' object does not support item assignment。正确做法是s = 'h' + s[1:]。
Q3 [单选] "a,b,c,d".split(",", 2) 的结果是?
- A.
["a", "b", "c", "d"] - B.
["a", "b", "c,d"] - C.
["a", "b"] - D. 报错
解答:B 正确。split(sep, maxsplit)的第二个参数限制拆分次数——最多拆 2 次,所以结果是["a", "b", "c,d"](最后一部分包含剩余内容,不再拆分)。
Q4 [多选] 以下哪些方法返回新字符串而不修改原字符串?
- A.
s.upper() - B.
s.replace("a", "b") - C.
s.strip() - D.
s.sort()
解答:A、B、C 都正确——字符串所有方法都返回新字符串,不修改原字符串(因为不可变)。D 错误——字符串没有sort()方法(排序用sorted(s)返回字符列表)。
Q5 [单选] f-string 中 f"{3.14159:.2f}" 的结果是?
- A.
"3.14159" - B.
"3.14" - C.
"3.1416" - D. 报错
解答:B 正确。.2f 表示保留 2 位小数四舍五入。3.14159 保留 2 位是 3.14(第三位是 1,舍去)。
Q6 [多选] 以下哪些是合法的字符串创建方式?
- A.
s = 'hello' - B.
s = "world" - C.
s = '''multi line''' - D.
s = str(123)
解答:全部正确。A 单引号、B 双引号、C 三引号(多行)、D 用 str() 构造函数将数字转为字符串。Python 的字符串创建非常灵活。
Q7 [单选] "-".join(["A", "B", "C"]) 的结果是?
- A.
"A-B-C" - B.
"A,B,C" - C.
["A-B-C"] - D.
"ABC"
解答:A 正确。join()用分隔符(这里是-)连接列表中的每个字符串元素,返回一个字符串。注意 join 是字符串方法,调用者是分隔符。
Q8 [多选] 关于 find() 和 index() 的区别,说法正确的是?
- A.
find()找不到返回 -1 - B.
index()找不到抛出 ValueError - C.
find()可以从右边开始查找 - D. 两者都可以指定起始查找位置
解答:A、B、D 正确。C 错误——从右边查找用rfind()和rindex()。两者都支持可选的start和end参数限定查找范围。
Q9 [单选] "hello".find("z") 的结果是?
- A. 0
- B. -1
- C. None
- D. 报错 ValueError
解答:B 正确。find()找不到子串时返回 -1,不抛异常。而index()找不到会抛 ValueError。这是两者最核心的区别。
Q10 [多选] 关于 Python 字符串的转义,以下正确的是?
- A.
\n表示换行符 - B.
\\表示一个反斜杠 - C.
r"C:\path"中\p不会被转义 - D.
\a表示制表符
解答:A、B、C 正确。D 错误——\t才是制表符(tab),\a是响铃符(ASCII Bell)。常用转义:\n换行、\t制表、\\反斜杠、\'单引号、\"双引号。