0%

Python3 字符串操作详解:从基础到高级技巧

Python 字符串:处理文本的这几十种方法,其实常用的就那些

写 Python 代码,字符串操作避不开。解析日志、处理用户输入、拼 SQL、格式化输出——天天都在跟文本打交道。

Python 的字符串方法多,但常用的就那么十几个。

字符串是什么,记住两点就够了

  • 不可变
1
2
3
4
5
s = "hello"
# s[0] = "H" # 报错!不能直接改

# 想改?创建新字符串
s = "H" + s[1:] # "Hello"

字符串一旦创建就不能改,所有”修改”操作都是创建新字符串。记住这点,写代码的时候就不会困惑了。

  • 序列,可以索引和切片
1
2
3
4
5
s = "Python"
s[0] # "P",从0开始
s[-1] # "n",倒数第一个
s[1:4] # "yth",从索引1到3,左闭右开
s[::-1] # "nohtyP",反转

切片是字符串最常用的操作之一,记住 [start:stop:step] 左闭右开就行。

查和找:在一段文本里找东西

判断开头结尾:

1
2
3
4
url = "https://example.com"

url.startswith("https") # True
url.endswith(".com") # True

找子串的位置:

1
2
3
4
5
6
7
8
text = "hello world, hello python"

text.find("world") # 6,返回第一次出现的位置
text.find("java") # -1,找不到返回-1
text.rfind("hello") # 13,从右边找

# 如果确定存在,用 index(找不到会报错)
text.index("world") # 6

日常用 find 就够了,返回 -1 表示没有。index 会抛异常,除非你很确定那个子串一定存在。

统计出现次数:

1
2
text.count("hello")   # 2
text.count("o") # 4

检查是否包含某个子串:

1
2
3
4
5
if "world" in text:
print("找到了")

if "java" not in text:
print("没有")

innot infind() != -1 更直观,推荐用这个。

改:替换、大小写、去空格

替换:

1
2
3
text = "hello world, hello python"
text.replace("hello", "hi") # "hi world, hi python"
text.replace("hello", "hi", 1) # "hi world, hello python",只替换第一个

大小写转换:

1
2
3
4
5
6
s = "Hello World"

s.upper() # "HELLO WORLD"
s.lower() # "hello world"
s.capitalize() # "Hello world",首字母大写其余小写
s.title() # "Hello World",每个单词首字母大写

去空格和换行:

1
2
3
4
5
6
7
s = "  \t hello \n  "
s.strip() # "hello",去掉两端空白
s.lstrip() # "hello \n ",去掉左边
s.rstrip() # " \t hello",去掉右边

# 去掉指定字符
"***hello***".strip("*") # "hello"

处理用户输入的时候,strip() 几乎是必用的——去掉用户不小心敲的空格。

拆和拼:字符串 ↔ 列表

拆:字符串变列表

1
2
3
4
5
6
7
8
9
10
11
s = "apple,banana,orange"
s.split(",") # ['apple', 'banana', 'orange']

# 默认按任意空白拆分(多个空格也OK)
"hello world".split() # ['hello', 'world']

# 控制拆分次数
"a,b,c,d".split(",", 2) # ['a', 'b', 'c,d']

# 按换行拆
"a\nb\nc".splitlines() # ['a', 'b', 'c']

拼:列表变字符串

1
2
3
fruits = ['apple', 'banana', 'orange']
",".join(fruits) # "apple,banana,orange"
" ".join(fruits) # "apple banana orange"

拼大量字符串的时候,千万别用 +=

1
2
3
4
5
6
7
8
9
10
# 错误: 慢,每次拼接都创建新字符串
result = ""
for i in range(10000):
result += str(i)

# 优化: 快,用列表收集最后 join
parts = []
for i in range(10000):
parts.append(str(i))
result = "".join(parts)

join+= 快 10 到 50 倍,数据量大的时候差距更明显。

格式化:把变量放进字符串

三种方式,我建议直接用第三种。

方式1:% 格式化(老式,不推荐)

1
"姓名:%s,年龄:%d" % ("张三", 25)

方式2:format()(还行,但不够简洁)

1
"姓名:{},年龄:{}".format("张三", 25)

方式3:f-string(Python 3.6+,推荐)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
name = "张三"
age = 25
f"姓名:{name},年龄:{age}" # 最直观,最快

# 还可以放表达式
f"明年年龄:{age + 1}"

# 数字格式化
f"价格:{price:.2f}" # 保留两位小数
f"百分比:{rate:.1%}" # 转成百分比

# 对齐
f"{"左":<10}" # 左对齐
f"{"右":>10}" # 右对齐
f"{"中":^10}" # 居中

f-string 比前两种都快,而且代码最干净。能用 f-string 就别用前面两种了。

判断:检查字符串是什么类型

1
2
3
4
5
6
"123".isdigit()       # True,全是数字
"abc".isalpha() # True,全是字母
"abc123".isalnum() # True,全是字母或数字
" ".isspace() # True,全是空白
"Hello".islower() # False
"HELLO".isupper() # True

这些方法在校验用户输入的时候很好用:

1
2
3
phone = input("请输入手机号:")
if not phone.isdigit():
print("手机号只能包含数字")

正则表达式:复杂匹配的终极武器

字符串方法只能做简单匹配,遇到复杂需求就得用正则了。

提取手机号:

1
2
3
4
5
6
import re

text = "我的电话是 13812345678"
match = re.search(r"1[3-9]\d{9}", text)
if match:
print(match.group()) # 13812345678

提取所有邮箱:

1
2
3
text = "联系我:test@example.com 或 admin@test.com"
emails = re.findall(r"\w+@\w+\.\w+", text)
# ['test@example.com', 'admin@test.com']

替换敏感信息:

1
re.sub(r"1[3-9]\d{9}", "***", text)

常用正则写法速查:

需求 正则
手机号 1[3-9]\d{9}
邮箱 \w+@\w+\.\w+
数字 \d+
中文 [\u4e00-\u9fa5]+
URL https?://[^\s]+

匹配中文的时候 \w 在 Python 里默认只匹配 ASCII,要匹配中文得用 [\u4e00-\u9fa5]

欢迎关注我的其它发布渠道