ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Python字符串详解:从定义、切片到格式化与类型转换

Python字符串详解:从定义、切片到格式化与类型转换 我见过太多人卡在字符串这一章不是因为它难而是因为没有把“字符串是一个对象”这件事放在心上。字符串在Python里出现频率极高爬虫拿回来的页面要清洗、接口返回的JSON要解析、日志要拼装、用户输入要校验说白了你写的十个程序里至少有八个绕不开它。这篇是零基础Python入门系列的第三篇前面讲完了变量、数据类型和基本运算这一篇就把字符串彻底拆开揉碎从定义方式、索引切片到常用方法、格式化、类型转换和报错排查一次讲透。如果你刚学完print(hello world)正想知道字符串到底还能干嘛或者你已经写了一些代码但遇到str转int报错、切片结果和预期不符这类问题这篇都适合你。我不会只丢一堆方法名让你背而是把每个操作背后的逻辑、适用场景和常见的坑都讲清楚这样你写代码的时候才能真的“顺手”。1. 先搞清楚字符串到底是个什么东西1.1 字符串的定义方式与转义字符字符串说白了就是一串字符的序列用引号包起来。Python里你有三种写法单引号hello、双引号hello、三引号hello或hello。这三种写法在绝大多数场景下没有本质区别但有一些约定俗成的使用偏好比如字符串内容里本身带了单引号你外层就用双引号包省得转义。举个实际例子你想表示Im a programmer如果外层用单引号就得写成I\m a programmer反斜杠看着就烦你直接用Im a programmer就干净利落。反过来如果内容里有双引号外层就用单引号。这是写代码避免踩坑的第一条经验不硬性规定但你照做会让代码舒服很多。三引号主要用来写多行文本。比如你要定义一个SQL语句在Python里拼多行字符串用三引号可以直接换行写读起来比用\n拼接清晰得多。我曾经在处理一段很长的接口文档模板时就是用三引号把整个模板包起来变量位置再用占位符替代维护起来非常方便。这里有一个小细节三引号里的换行符会原样保留有些时候你需要.strip()把首尾多余的换行清掉。转义字符是新手容易懵的地方。\n表示换行、\t表示制表符、\\表示反斜杠本身。一个最常见的坑是Windows下的文件路径比如C:\Users\name你直接写在字符串里会发现\U被当作Unicode转义程序直接报错。解决方式有两个一是把反斜杠写成双反斜杠C:\\Users\\name二是在字符串前面加一个r写成rC:\Users\name表示原始字符串所有转义都不处理。做文件操作时我几乎都用r前缀省心。1.2 字符串是不可变对象这一点决定了所有操作的返回值这是理解字符串最重要的一句话字符串是不可变对象。你执行任何“修改”字符串的操作Python都不会真的在原字符串上改而是重新创建一个新字符串返回。很多人写代码时想当然地以为调用了replace或upper之后原串就变了结果一打印发现原串纹丝不动这就是没理解不可变性。举个例子s hello s.upper() print(s) # 输出还是 hello你必须写成new_s s.upper()修改后的结果才拿得到。这个特性不仅适用于字符串后面学到的元组也是不可变的这个“不可变”思维最好早一点刻在脑子里能帮你避免后面很多莫名其妙的bug。为什么Python要把字符串设计成不可变往深了说字符串经常被当作字典的键、集合的元素如果可变哈希值就乱了整个数据结构都会崩。所以这是一层安全设计。咱们初学阶段不用太较真但你要记住一条实操原则需要生成新内容就把返回值接住。1.3 字符串的长度与空字符串len()函数用来获取字符串长度比如len(hello)返回5。这里要特别注意中文、英文、数字、标点在len()眼里都是一个字符一个中文汉字占一个长度。空字符串的长度是0它可不是None两者完全不同。None表示“没有值”表示“一个空的值”这个区别在做接口判断时经常用得上——判断用户是否输入了内容应该用if user_input 或者if not user_input而不是if user_input is None。2. 索引和切片取字符串里的一段内容2.1 正索引、负索引与越界问题字符串是序列所以可以按下标取字符。这里Python给了一个其他语言不一定有的便利索引不仅可以从左往右数从0开始还可以从右往左数用负数。s[0]是第一个字符s[-1]是最后一个字符。这在实际写代码时特别香比如你要拿一个文件名里的后缀名filename[-3:]就直接切出来了不用先数长度再算位置。新手常见的问题是索引越界。s abc你写s[5]会直接抛IndexError: string index out of range。这在循环遍历时尤其容易发生——比如你想隔一个取一个结果循环边界没控制好访问到不存在的下标。遇到这种报错先检查下标范围len(s)-1才是最后一个合法正索引。2.2 切片语法与步长的实际用法切片是Python里用得非常多的操作语法是[start:end:step]左闭右开包含start但不包含end。我当初学的时候老记不住“不包含end”这一点后来用了一个生活化类比就像排队测体温喊到“1号到5号”进房间通常是1、2、3、4进5号在门口等下一批。切片也一样s[1:5]取的是下标1、2、3、4的字符最后一个5不取。重点来了start、end、step三个参数都可以省略。s[:3]取前三个字符s[3:]去掉前三个取剩下的这种写法在处理固定格式的数据时非常常用。比如一段文本前几个字符是日期后面是正文你直接date_part text[:8]、body text[8:]就拆开了不用去数到底有多少个字符。步长step不止能正着走还能负着走。你写s[::-1]意思是“从头到尾每次跨一步但方向反过来”结果就是把字符串倒序输出。这是实现字符串逆序最简单的方式比循环拼接不知道高到哪里去了。很多教材和笔试题都会拿这个考你记住了就是送分题。这里有一个细节值得单独说一下切片不会越界报错。s abc你写s[5:10]不会崩返回的是空字符串。这和索引访问完全不同因为切片本身设计得比较宽松超出范围的部分自动忽略。利用这个特性你可以放心地做“安全截取”比如截取前10个字符就算字符串只有3个字符也不会报错。2.3 逆序、间隔取字符等高频场景实际写代码时逆序输出字符串大概是出现频率最高的需求之一。除了s[::-1]你还可以用s[-1::-1]效果一样。如果面试官问“不用切片怎么逆序”你可以用.join(reversed(s))——reversed(s)返回一个反向迭代器再用join把它拼回字符串。这个写法在刷题时经常用到我建议两种都记熟。间隔取字符用步长就能实现比如s[::2]取出偶数位置的字符s[1::2]取出奇数位置的字符。在处理一些规律性文本、做数据抽样时这种写法比循环判断下标简单得多。我之前处理过一串基因序列文本想每三个字符分组就是[s[i:i3] for i in range(0, len(s), 3)]这种思路虽然那会儿还没学列表推导式但切片的底子已经够用了。3. 字符串常用方法处理文本的常用工具箱3.1 大小写转换与判断方法大小写转换是英文文本处理的最基础操作。s.upper()全转大写s.lower()全转小写s.capitalize()首字母大写其余小写s.title()每个单词首字母大写。这些方法在写搜索功能时特别有用——用户输入关键词的大小写不可控统一转成小写再做匹配就不会因为大小写差异漏掉结果。判断类方法用得也不少s.isalpha()判断是否全是字母s.isdigit()判断是否全是数字s.isalnum()判断是否全是字母或数字s.isspace()判断是否全是空白字符。这些判断在表单校验里是主力。比如注册时要求用户名只能包含字母和数字你就可以写if not username.isalnum():然后提示用户。不过要提醒一句isdigit()对中文数字和某些Unicode数字字符也会返回True比如①.isdigit()就是True所以如果只允许阿拉伯数字还得配合其他判断后面类型转换部分我会再细说。3.2 strip、split、join清洗与拆分重组的三板斧从外部拿到的文本几乎都是脏的。爬虫抓回来的HTML里有大量空格、换行、制表符用户提交的表单里可能有意外输入的空格。这时候strip()就是你的清洁工。s.strip()去掉首尾的空白字符s.lstrip()只去左边s.rstrip()只去右边。还有一个隐藏用法strip()可以传参指定要去掉的字符比如s.strip(*)去掉首尾的星号。我自己做文本预处理时几乎每一条原始数据进来都要先strip()一下不然下一步的匹配经常出幺蛾子。split()是按指定分隔符把字符串拆成列表。s.split(,)把字符串按逗号拆分返回一个列表不传参数时按任意空白字符拆分连续多个空格也按一个处理。这在处理CSV行数据、日志文本、配置项时是家常便饭。我见过有人要用文本里的空格把一句话拆成单词列表直接line.split()就完事比line.split( )稳得多因为后者在连续空格时会拆出空字符串。join()是split()的反向操作把列表里的元素用指定分隔符拼成一个字符串。-.join([2025, 01, 01])得到2025-01-01。这里有一个Python老手都会强调的坑join是字符串的方法不是列表的方法。正确写法是分隔符.join(列表)新人经常写成列表.join()然后报AttributeError。我教过几个朋友写Python几乎都在这个地方卡了一下写代码时多留个心眼。split和join合起来能做很多事。比如你有一段英文句子想把单词顺序完全倒过来——“hello world python”变成“python world hello”思路就是先split()得到列表列表reverse()再join回去。三步就搞定不用自己去数空格位置、不用手动拼接。这个“先拆再组”的思路其实是一种很通用的文本处理套路值得到处套用。3.3 find、index、replace查找与替换的关键细节查找子串有两个常用方法s.find(sub)返回子串第一次出现的下标找不到时返回-1s.index(sub)行为和find几乎一样但找不到时会抛ValueError。我个人的习惯是在正常业务逻辑里多用find因为用-1判断比捕获异常更轻量、更不容易打断流程在写测试、或者确实认定子串一定存在时才用index。replace(old, new)是把所有匹配到的子串替换成新内容。比如a-b-c.replace(-, /)得到a/b/c。replace的第三个参数可以限定替换次数aaaa.replace(a, b, 2)只替换前两个。这个参数在处理“只改前几处”的场景时很实用。要注意的还是不可变性——所有替换结果必须接住原字符串不动。查找和替换在文本清洗场景里往往是组合拳先用strip()去掉首尾空白再用replace()把干扰字符换掉接着用split()拆出目标字段。我处理接口返回的大段HTML时经常是先把标签字符替换成空格再用split()把纯文本挑出来。这种思路比正则表达式简单得多适合初学和快速处理。4. 字符串格式化拼字符串的正确方式4.1 从%格式化到format方法字符串拼接大概是所有新手最先学会的字符串操作我的名字是 name 今年 str(age) 岁这种写法看着没问题但一旦变量多了、句子长了加号满天飞读起来非常痛苦而且容易漏掉类型转换。格式化就是为了解决这个痛点。最早期的写法是%格式化也是从C语言继承过来的思路。我的名字是%s今年%d岁 % (name, age)%s表示这里放字符串%d表示放整数。这个写法在老代码里还能经常看到但它有几个缺点占位符和后面的参数要严格对位一多就容易错而且类型不匹配还会报错。后来Python推出了format()方法用花括号做占位符我的名字是{}今年{}岁.format(name, age)默认按顺序填充也可以指定顺序或参数名比%灵活了不少。如果你在维护一些老项目这两种写法都要看得懂。4.2 f-string现代Python的推荐方案性能更好从Python 3.6开始f-string成为格式化输出的第一选择我强烈推荐你直接用这种。写法是在字符串前面加一个f然后在花括号里直接放变量或表达式f我的名字是{name}今年{age}岁。它最大的优点就是直观——什么地方放什么内容一眼就看明白不需要再到后面去找参数一一对应。f-string里还能直接写表达式比如f面积是{width * height:.2f}平方米后面的:.2f表示保留两位小数。这在做数据展示和日志输出时太方便了我以前拼SQL查询条件、拼接口请求体全靠f-string代码可读性比老式写法高一个档次。性能和可读性双优为什么还要提format和%因为你在实际项目里会碰到老代码。Python升级不是一蹴而就的存量系统里有大量使用%或format的代码你得能读得懂、改得动。而且有些场景下模板字符串本身是从配置或数据库读出来的不能提前加f这种时候format()反而更合适。学新的是为了写得爽懂旧的是为了活得久两者不冲突。4.3 模板字符串在实际项目中的角色格式化还有一个相关的概念叫模板字符串在Python里对应string.Template模块支持用$做占位符Template(Hello, $name)。这种写法在需要把模板和数据彻底分离的场景里很好用比如批量生成邮件、报告、配置文件——把模板单独放一个文件读进来后替换变量就行不用把整段文案硬编码在代码里。它的写法比f-string更简单但功能也弱一些只能做变量替换不能放表达式。日常开发里f-string够用但如果你在处理“模板来自外部”的架构Template值得了解一下。5. 字符串与其他类型的“跨界”转换5.1 字符串与数字的互转最容易踩坑的地方str(123)把数字变成字符串这个基本没坑。反过来int(123)把纯数字字符串变成整数float(3.14)变成浮点数这里面的坑就多了。最常见的一个int(12.5)会直接报ValueError: invalid literal for int()。很多新手以为int()能把任何数字形式的字符串转成整数实际上它要求字符串必须是纯整数格式带小数点不行、带空格都不行。你要转带小数的得先float(12.5)再int()或者直接用float。另一个例子是int(12 ——字符串末尾有空格一样报错必须先strip()。再一个经常遇到的场景用户输入的金额可能带逗号、带货币符号、带千分位比如1,234.56。直接float()肯定崩你需要先把,去掉float(1,234.56.replace(,, ))。这些实操经验文档里不会专门写但处理真实数据时几乎避不开。这里有一个需要强调的思维校验和转换是两件事。你可以在转之前先用isdigit()或replace异常捕获来判断但isdigit()的判断结果不等于“可以安全int()”。比如12.5.isdigit()返回False你能安全地用int()吗不能因为它根本不是整数格式。反过来12.isdigit()返回Trueint(12)没问题。所以除了记住方法也要记得“接口返回的字符串不可信先strip、先replace、再转换”这条处理原则。5.2 字符串与JSON的互转接口开发离不开的操作做爬虫或者调接口的同学对JSON转字符串一定不陌生。json.dumps(data)把字典或列表变成JSON字符串json.loads(s)把JSON字符串解析回Python对象。这两个函数的细节非常多而且经常踩坑。json.dumps的坑主要是两个一是中文默认会被转成\uXXXX这种Unicode转义序列显示出来全是乱码解决办法是加参数ensure_asciiFalse二是默认会把所有内容紧凑输出空格全挤在一起调试时不好看可以加indent4让它带缩进。我调试接口时几乎必加这两个参数打印出来的内容才能看懂。json.loads的坑主要是格式严格——JSON标准里键和字符串值必须用双引号单引号会导致解析失败。如果你拿到的字符串是Python风格的、键用单引号先自己替换一下或者用ast.literal_eval处理不然json.loads直接甩一个JSONDecodeError。还有一点json.loads(null)返回Nonejson.loads(12)返回整数12json.loads(true)返回True它不只是解析对象和数组这些类型也要有预期。5.3 字符串与日期时间格式化输出与解析处理日期时间字符串是绕不开的中间载体。datetime对象要展示给人看得先转成字符串前端传过来的日期是字符串要参与运算、排序得先解析成datetime对象。strftime是把日期对象格式化成字符串strptime是把字符串解析成日期对象这两个函数的名字长得像但方向完全相反。格式化符号要记几个常用的%Y四位年份、%m两位月份、%d两位日期、%H时、%M分、%S秒。datetime.now().strftime(%Y-%m-%d %H:%M:%S)得到2025-06-15 14:30:00这个格式在写日志、存数据库时几乎是标配。反过来datetime.strptime(2025-06-15, %Y-%m-%d)把字符串解析成日期对象。这里最坑的是格式必须完全匹配字符串是2025/06/15你就得用%Y/%m/%d差一个斜杠都报错。在拿到外部输入时先预设好格式再解析不要指望Python自动识别。6. 字符串的判断、比较与排序逻辑判断里的隐藏细节6.1 与 is 的本质区别判断两个字符串是否相等第一反应是这没错。但如果你看到is也要留个心眼。比较的是值只要内容相同就返回Trueis比较的是内存地址只有两个变量指向同一个对象才返回True。对于字符串Python解释器会对一些短的字符串做缓存复用所以有时a hello; b hello; a is b返回True给了很多人“is也能判断字符串相等”的错觉。但遇到长字符串、动态拼接出来的字符串is的结果可能就变了。咱们写代码就把原则定死比较值就用判断是不是同一个对象才用is别混用。6.2 大小比较按字符的Unicode码点逐个比字符串也能用、比较大小规则是按Unicode码点逐字符比。abc abd返回True因为前两个字符a、b相同第三个字符c的码点小于d。b abc也返回True因为它先比第一个字符b和a直接就分出高下了后面的内容根本不看。这个规则在排序时非常有用配合sorted()可以对字符串列表按字典序排序比如sorted([banana, apple, cherry])得到[apple, banana, cherry]。这里有一个很多人在实际项目中会踩的坑字符串排序和数字排序语义不同。sorted([10, 9, 8])得到的是[10, 8, 9]因为它是按字符逐个比第一个字符1小于8所以10排最前。如果你期望的是数字排序得先把元素转成整数sorted(map(int, [10, 9, 8]))。处理从文件或接口读取的“看起来像数字”的字符串时一定要想清楚到底要按什么排序。6.3 包含判断in、startswith、endswith的适用场景in操作符判断一个字符串是否包含另一个字符串返回布尔值。world in hello world返回True。这个最基本的包含判断在过滤数据、搜索关键词时用得非常频繁。startswith()和endswith()则判断开头和结尾我经常用它们做文件类型判断filename.endswith(.py)、url.startswith(https://)比用in更精确也更直观。这三个方法在业务逻辑里都是高频率选手写代码时可以优先想到它们。还有一个细节startswith和endswith支持传入元组比如filename.endswith((.jpg, .png, .gif))一次判断多个后缀这在写文件处理脚本时能省不少if嵌套。6.4 字符串排序sorted与sort的区别很多人分不清sorted()和列表的sort()sorted()会返回一个新列表原来的列表不变所以sorted()可以作用在字符串的字符序列上sort()是列表自身的方法直接在原列表上排序、返回None。你要给字符串里的字符排序比如打乱顺序的单词dbca想排成abcd要分三步走sorted(dbca)得到字符列表[a, b, c, d]再用.join()拼回字符串。这个“拆开-排序-重组”的思路也是字符串处理里非常经典的套路。如果你给sorted()传入reverseTrue就能得到逆序排序的结果。7. 遇错不慌字符串操作最常见的报错与排查思路7.1 报错速查表几类高频异常写字符串操作代码报错是难免的。我整理了一个速查表你在崩了之后对着查能省很多时间异常类型典型触发场景排查方向TypeError: can only concatenate str用拼接字符串时混入了数字用str()包一下数字或改成f-stringValueError: invalid literal for int()int()转换带小数、带空格、非数字的字符串先strip()再看格式必要时float()过渡IndexError: string index out of range用下标访问字符串超出范围检查下标边界用len(s)-1做上限AttributeError: str object has no attribute方法名拼错或用错对象调用方法确认方法属于字符串还是列表核对拼写TypeError: string indices must be integers用字符串当下标访问字符串检查是不是把子串当成下标用了JSONDecodeErrorjson.loads解析了不合法JSON检查引号是单还是双字符串是否有残缺ValueError: time data does not match formatstrptime格式和字符串不匹配对比格式符号和字符串的实际结构7.2 我排查字符串问题的一套固定流程遇到字符串相关报错我的排查顺序基本是固定的。第一步看异常类型和提示行定位到具体代码行这步能过滤掉一半的问题。第二步打印原始字符串的repr()形式——注意用repr()而不是直接print因为repr()会把换行符、制表符、空格原样显示出来你能看到字符串里藏着的空白和转义内容。我以前被一个“看起来一样但比较不等”的问题卡了很久最后用repr()才发现一个字符串末尾多了个换行符。第三步是针对转换类报错先单独把待转换的变量提出来手动执行一次int()或json.loads()看能不能复现。这样能把“是数据问题”还是“是代码逻辑问题”快速分开。排查思路理清楚了再去看代码就清晰很多。最后别忘了回头检查输入的来源——是从文件读的、接口返回的还是用户输入的不同来源的脏数据形态不一样你也能针对性做清洗。7.3 实际场景中的一次避坑实录举一个我最近碰到的例子。在写一个数据处理脚本时要从一个文本文件里读取一批数字求和我用int()逐行转换结果程序崩在ValueError上。用repr()检查每行内容发现有些行末尾带着\r\n这种Windows风格换行符数字字符串里混着\r自然转不了。解决方式很简单每行先strip()再去转换。这个坑看起来不起眼但真实项目里数据来源五花八门文件编码、换行符、首尾空格、隐藏字符每一项都能把你绊一跤。这也印证了前面反复强调的那句话外部拿到的字符串默认不可信能清洗就先清洗。8. 小结之外给你的一条实际建议如果这一篇读下来你只记住一件事我希望是处理字符串前先想清楚“数据从哪来、要变成什么样、有哪些边界情况”。很多报错和奇怪行为本质上都是这三个问题没想清楚导致的。代码写不下去的时候不要急着翻文档先把那个字符串用repr打出来看看大多数问题立刻就有答案了。我教人的时候总说一句话字符串方法不要死记多用几次、多踩几个坑自然就记住了。你写爬虫会用到strip、split、replace写接口会用到json.dumps、json.loads写日志会用到f-string处理日期会用到strftime。每一个方法都是在场景里练出来的光看文档永远记不牢。这一篇讲到的所有代码建议你全部自己在编辑器里敲一遍改一改参数故意制造几个报错再解决掉这个过程比读十遍文章都管用。下一篇我会讲Python的列表和元组你可以先想想列表和字符串有哪些相似之处又有哪些截然不同的特性带着这个问题来学起来会快很多。
返回列表