Python学习之str重要函数
前言这一篇是把str的方法按用途梳理一遍。与其零散地记有个strip、有个split不如按你手上要解决的问题来归类我要找东西、我要判断、我要切分、我要清理、我要改大小写、我要格式化。分类记住了用到时自然能想起该翻哪一页。要先纠正一个说法上的习惯str的这些函数准确说是方法method得由字符串实例来调用比如abc.upper()而不是upper(abc)。它们全都是读方法——str不可变任何方法都不会改动调用它的那个字符串只会返回一个新串。另一个高频误解集中在strip很多人以为strip(abc)是去掉开头的 abc其实它的参数是一组字符会把两端所有落在这组字符里的字符逐个剥掉。本文按功能分组列方法签名以 Python 官方文档为准代码基于 Python 3.8 及以上。Python 2.7 已于 2020 年 1 月 1 日停止维护dict.iteritems()、xrange、unicode那些写法本文不采用。一、查找与判断查找类方法告诉你在哪里或有没有。# 适用于 Python 3.8s Hello, Worldprint(s.find(o)) # 4 找不到返回 -1print(s.rfind(o)) # 8 从右往左找第一个print(s.count(l)) # 3 非重叠出现次数print(s.startswith(He)) # Trueprint(s.endswith(ld)) # Trueprint(s.startswith((Hi, He))) # True 可传元组一次判多个s.find(sub)找不到返回-1而s.index(sub)找不到会抛ValueError。要自己判断在不在就用find要找不到就是 bug就用index。判断类方法全都以is开头返回布尔值方法为真的条件s.isalpha()非空且全是字母s.isdigit()非空且全是数字字符s.isalnum()非空且全是字母或数字s.isspace()非空且全是空白s.islower()/s.isupper()有大小写字符且全为小写 / 大写s.isidentifier()是合法的 Python 标识符# 适用于 Python 3.8print(abc.isalpha()) # Trueprint(abc1.isalpha()) # Falseprint(.isalpha()) # False 空串对 is* 一律返回 Falseprint(Hello.islower()) # False 有大写字母注意is系列对空串统一返回False别把空当成通过校验。二、切分与合并方法返回关键点s.split(sepNone, maxsplit-1)列表sepNone时连续空白算一个分隔符s.rsplit(sepNone, maxsplit-1)列表从右往左切s.splitlines(keependsFalse)列表按各种换行符切行s.partition(sep)三元组保留分隔符只切一刀s.join(iterable)字符串分隔符在前# 适用于 Python 3.8print(a b c.split()) # [a, b, c] 连续空白算一个print(a,b,,c.split(,)) # [a, b, , c] 会留空串print(a,b,c.rsplit(,, 1)) # [a,b, c] 从右只切一次print(-.join([a, b])) # a-bsplit()不传参数和split(,)是两套算法前者把连续空白视作单个分隔符且不产生空串后者严格按分隔符切、连续分隔符会切出空串。这一点是新手最常踩的坑之一。join的参数必须全是字符串混进数字会抛TypeError得先map(str, ...)转换。三、清理与填充# 适用于 Python 3.8print( x .strip()) # xprint( x .lstrip()) # x 只去左边print(xxabcxx.strip(x)) # abc 两端所有 x 都被剥掉print(42.zfill(5)) # 00042print(ab.center(6, *)) # **ab**print(ab.ljust(4, .)) # ab..print(ab.rjust(4, .)) # ..abstrip、lstrip、rstrip的参数都是字符集合不是完整前缀/后缀。要按前后缀去除应改用 3.9 才加入的removeprefix/removesuffix# 适用于 Python 3.9print(TestHook.removeprefix(Test)) # Hookprint(MiscTests.removesuffix(Tests)) # Miscprint(BaseTestCase.removeprefix(Test)) # BaseTestCase 前缀不匹配就原样返回3.9 以前的替代写法是s[len(p):] if s.startswith(p) else s虽然啰嗦但行为一致。四、大小写与映射# 适用于 Python 3.8print(Hello.upper()) # HELLOprint(Hello.lower()) # helloprint(hello world.title()) # Hello Worldprint(aBc.swapcase()) # AbCprint(Straße.casefold()) # strasse 比 lower 更彻底适合做比较casefold()是lower()的强化版专门用于忽略大小写的比较德语ß在casefold()下会变成ss而lower()不会。做两个字符串是否等价的判断时优先用casefold()。str.translate配合str.maketrans能做批量单字符替换或删除# 适用于 Python 3.8print(hello.translate(str.maketrans(, , aeiou))) # hllprint(abc.translate(str.maketrans(abc, xyz))) # xyz五、格式化三种主流方式方式写法说明f-stringf{name}3.6 起3.8 起支持调试符3.12 起可嵌套同类引号str.format{0}.format(x)位置 / 关键字都能用还有格式规格%%s % x老式写法新代码不建议# 适用于 Python 3.8name, score 小明, 95.6print(f{name} 的分数是 {score:.1f}) # 小明 的分数是 95.6print({0} 的分数是 {1:.1f}.format(name, score))print(f{score}) # score95.6 调试符3.8 起:.1f这类冒号后面的部分叫格式规格format specf{x:.1f}和{x:.1f}.format(x...)共用同一套语法两边的规格可以互通。3.12 之前f-string 里不能再嵌套同一种引号3.12 起PEP 701放开了这个限制。实战清洗一段半结构化的文本下面这段把查找、切分、清理、判断串起来把一段乱糟糟的文本整理成结构化记录。# 适用于 Python 3.8RAW alice , 28 , Engineerbob,31,Designercarol , 45 , Managerdef parse_records(raw):records []for line in raw.splitlines():line line.strip()if not line: # 跳过空行continueparts [p.strip() for p in line.split(,)]if len(parts) ! 3: # 字段数不对跳过continuename, age, job partsif not age.isdigit(): # 年龄必须是纯数字continuerecords.append({name: name, age: int(age), job: job})return recordsfor r in parse_records(RAW):print(f{r[name]:6}|{r[age]:3}|{r[job]})# alice | 28|Engineer# bob | 31|Designer# carol | 45|Managersplitlines()负责切行strip()去掉行首尾空白列表推导式里的strip()去掉每个字段两侧的空白isdigit()做字段校验。每一步都围绕用对方法而不是写一堆手写循环。常见坑点把strip当去前后缀❌ 以为参数是前缀字面量www.example.com.strip(cmowz.)期待只动开头✅ 参数是字符集合两端凡属于该集合的字符都被逐个剥掉官方文档给的这个例子结果就是example按前后缀去除要用www.example.com.removeprefix(www.)3.9 起split()和split(,)混用❌ 处理逗号分隔的 CSV 时写line.split()字段里的空格被当成分隔符✅ 明确分隔符时写line.split(,)只有按空白分词才用无参split()find返回 -1 直接拿去当索引❌s[s.find(x) 1:]没找到时返回整串✅ 先判-1或改用partition并检查sep是否为空is*方法对空串返回 False❌if name.isalpha():于是空名字被当成不合法逻辑方向写反✅ 想表达仅当非空且全字母用name.isalpha()想表达要么是字母要么是空写成name or name.isalpha()join里混入非字符串❌,.join([1, 2, 3])→TypeError✅,.join(map(str, [1, 2, 3]))方法返回值没接住❌s.strip()单独一行以为s变了✅s s.strip()所有str方法都返回新串用lower()做大小写无关比较❌Straße.lower() STRASSE.lower()为False✅ 用casefold()Straße.casefold() strasse.casefold()为True沿用 Python 2 的旧写法❌string.upper(s)的函数式调用、unicode(s)、s.decode(utf-8)处理普通str✅ Python 3 用方法式s.upper()类型统一是strPython 2.7 已于 2020 年 1 月 1 日 EOL总结用途代表方法查找find/rfind/count/startswith/endswith判断isalpha/isdigit/isalnum/isspace切分split/rsplit/splitlines/partition合并join清理strip/lstrip/rstrip/removeprefix/removesuffix大小写upper/lower/casefold/title/swapcase映射translatemaketrans格式化f-string /str.formatstr的方法看着多但分类很干净记住查找、判断、切分、合并、清理、大小写、格式化这七类用到时按需求对号入座就行。真正需要反复提醒的只有两点这些都是方法不是函数以及它们一律返回新串——str不可变没有任何一个方法会就地改动原来的字符串。