Python技术迷

Python 中如何将字符串转换为小写?

Python 里把字符串转小写,别只知道 lower()

导入脚本跑完,邮箱去重还是重复。

一看数据,气得人想关电脑:

[email protected]
[email protected]
[email protected]

肉眼看是一个邮箱,程序看是三个字符串。 这种问题我一般不先怀疑数据库,也不先怀疑去重逻辑,先看清洗有没有做大小写统一。很多脏数据就是这么混进去的。

Python 里最常用的写法就一行:

email = "[email protected]"
email = email.lower()

print(email)
# [email protected]

lower() 会返回一个新的字符串,不会改原来的字符串。

这一点得记一下。字符串在 Python 里是不可变对象,你写:

name = "OrderStatus"

name.lower()

print(name)
# OrderStatus

这段代码看着调用了 lower(),其实啥也没接住。线上清洗脚本里我见过这种写法,跑完一堆数据,结果字段还是原样。正确写法是重新赋值:

name = "OrderStatus"
name = name.lower()

print(name)
# orderstatus

如果只是普通英文、接口字段、日志级别、状态码这些,用 lower() 就够了。

比如接口传来的状态值不稳定:

raw_status = " PAID "

status = raw_status.strip().lower()

if status == "paid":
    print("订单已支付")

这里我一般会顺手加上 strip()。因为真实数据里,大小写不是唯一的问题,前后空格也很常见。尤其是 Excel 导入、CSV 导入、人工后台录入,别太相信输入源。

再比如清洗一批用户名:

users = ["Admin", "testUser", "OPS", "guest "]

clean_users = []
for user in users:
    clean_users.append(user.strip().lower())

print(clean_users)
# ['admin', 'testuser', 'ops', 'guest']

别为了这一点写得花里胡哨。数据量不大,循环就挺清楚。后面真慢了,再说优化。

当然,也可以写成列表推导:

users = ["Admin", "testUser", "OPS", "guest "]

clean_users = [user.strip().lower() for user in users]

print(clean_users)

这个写法适合一眼能看懂的场景。要是里面还夹着判空、字段拆分、异常兜底,我宁愿拆成普通循环,后面排问题省事。

有个坑也得提一下。lower() 不是类型转换器,它只处理字符串。你给它塞个 None 或数字,它会直接报错:

value = None

print(value.lower())

报错大概是这样:

AttributeError: 'NoneType' object has no attribute 'lower'

导入脚本里这种最常见。某一行字段为空,脚本跑到一半炸了。我的习惯是先写一个小函数,把脏值挡在外面:

defnormalize_text(value):
if value isNone:
return""

return str(value).strip().lower()

row = {
"email": " [email protected] ",
"level": "ERROR",
"remark": None,
}

email = normalize_text(row.get("email"))
level = normalize_text(row.get("level"))
remark = normalize_text(row.get("remark"))

print(email, level, remark)
# [email protected] error

这段不高级,但抗揍。 我宁可这里啰嗦一点,也不愿意让清洗任务凌晨跑到第 8 万行突然挂掉。

还有一个方法叫 casefold(),很多人平时用不到,但知道它有必要。它比 lower() 更适合做“不区分大小写”的比较,尤其涉及一些非英文字符时。

left = "Straße"
right = "STRASSE"

print(left.lower() == right.lower())
# False

print(left.casefold() == right.casefold())
# True

所以我的取舍一般是这样:

普通业务字段、英文状态、邮箱、用户名,用 lower()。

要做更严格的大小写无关比较,特别是多语言文本,用 casefold()。

比如封装成一个判断函数:

defsame_text(left, right):
if left isNoneor right isNone:
returnFalse

return str(left).strip().casefold() == str(right).strip().casefold()

print(same_text("Admin", " admin "))
# True

print(same_text("Straße", "STRASSE"))
# True

还有个细节,别把“转小写”和“改显示文案”混在一起。

比如商品标题:

title = "iPhone 15 Pro Max"

你要是直接:

title = title.lower()

结果就变成:

iphone 15 pro max

这在搜索索引里可能没问题,但拿去页面展示就很怪。 所以我一般会分两个字段,一个用于展示,一个用于检索:

product = {
"display_name": "iPhone 15 Pro Max",
}

product["search_name"] = product["display_name"].casefold()

print(product)

排查搜索搜不到、去重不准、状态判断失效这类问题时,我会先看这种字段有没有统一清洗,而不是上来就翻一堆业务代码。

Python 转小写本身没什么复杂的。

真正容易出问题的是这几个地方:

lower() 返回新字符串,别忘了接收。

清洗前先处理空值。

真实数据通常还有空格,strip() 经常要一起用。

普通英文用 lower(),严格比较用 casefold()。

展示字段和检索字段别混着改。

这东西小,但线上脏数据最喜欢从这种小口子钻进来。