3、字符串操作数:字符串的拼接、重复、索引与切片操作
字符串这东西,说白了就是一堆字符排排坐。Python 里处理字符串特别灵活,我刚开始学的时候觉得不就是文字嘛,有啥好讲的?后来做日志解析项目才发现,字符串操作要是玩不转,代码能写得又臭又长。
今天咱们就把字符串的四个核心操作——拼接、重复、索引、切片——彻底讲明白。这些操作你天天都会用到,但用好用坏差别很大。
3.1 字符串拼接:不只是加号那么简单
字符串拼接,最直观的方式就是用 + 号。比如:
first_name = "张"
last_name = "三"
full_name = first_name + last_name
print(full_name) # 输出:张三
这很简单对吧?但我在项目中遇到过一个问题:用 + 拼接大量字符串时,性能会急剧下降。为什么呢?因为字符串是不可变对象,每次拼接都会创建新对象。
避坑指南:我曾经在一个日志处理脚本里用 + 拼接了上万条记录,结果跑了快 10 秒才出结果。后来换成 join() 方法,0.1 秒就搞定了。
来看看 join() 的正确用法:
words = ["Python", "是", "一门", "优雅的", "语言"]
sentence = " ".join(words)
print(sentence) # 输出:Python 是一门优雅的语言
我个人习惯是:拼接 3 个以下用 +,超过 3 个就用 join()。你想想看,join() 会预先计算总长度,一次性分配内存,效率自然高。
还有一种拼接方式——格式化字符串。Python 3.6 以后推荐的 f-string:
name = "小明"
age = 18
info = f"我叫{name},今年{age}岁"
print(info) # 输出:我叫小明,今年18岁
嗯,这里要注意:f-string 里可以放表达式,不只是变量名。
price = 9.9
count = 3
total = f"总价:{price * count:.2f}元"
print(total) # 输出:总价:29.70元
3.2 字符串重复:乘号的妙用
字符串重复用 * 操作符。说实话,这个功能我第一次看到时觉得挺鸡肋的,后来才发现真香。
line = "-" * 50
print(line) # 输出:50个横线
我在做命令行工具时经常用它来画分隔线:
def print_separator(char="=", length=60):
print(char * length)
print_separator() # 输出:60个等号
print_separator("*", 30) # 输出:30个星号
重复操作还能用来生成模板字符串:
template = "Hello " * 3 + "World"
print(template) # 输出:Hello Hello Hello World
小技巧:重复操作符的右操作数必须是整数。如果是浮点数,Python 会报错。我曾经踩过这个坑,把 3.0 传进去,结果程序直接崩溃。
3.3 字符串索引:从 0 开始的世界
字符串索引,说白了就是给每个字符编个号。Python 的索引从 0 开始,这跟大多数编程语言一样。
text = "Python"
print(text[0]) # 输出:P
print(text[1]) # 输出:y
print(text[5]) # 输出:n
但 Python 有个特别贴心的设计——负索引。从右往左数,从 -1 开始:
print(text[-1]) # 输出:n
print(text[-2]) # 输出:o
print(text[-6]) # 输出:P
为什么会这样设计?说白了就是为了方便取末尾的字符。我写代码时经常用 text[-1] 取最后一个字符,比 text[len(text)-1] 简洁多了。
注意:索引越界会抛出 IndexError。我曾经在循环里忘了检查字符串长度,结果程序跑着跑着就崩了。记住:索引范围是 0 到 len(s)-1 或 -len(s) 到 -1。
3.4 字符串切片:最强大的操作
切片操作,我觉得是 Python 字符串最优雅的设计。语法是 [start:stop:step],三个参数都是可选的。
text = "Hello, Python!"
print(text[0:5]) # 输出:Hello
print(text[7:13]) # 输出:Python
print(text[:5]) # 输出:Hello(省略start,从开头开始)
print(text[7:]) # 输出:Python!(省略stop,到结尾结束)
print(text[:]) # 输出:Hello, Python!(复制整个字符串)
步长参数 step 是切片的高级玩法:
numbers = "0123456789"
print(numbers[::2]) # 输出:02468(每隔一个取一个)
print(numbers[1::2]) # 输出:13579(从索引1开始,每隔一个取一个)
print(numbers[::-1]) # 输出:9876543210(反转字符串)
我个人觉得 [::-1] 反转字符串这个技巧特别实用。我在做回文检测时就用它:
def is_palindrome(s):
return s == s[::-1]
print(is_palindrome("radar")) # 输出:True
print(is_palindrome("hello")) # 输出:False
核心要点:切片不会引发 IndexError。如果起始索引超出范围,Python 会自动调整到边界值。这是切片和索引最大的区别。
text = "Python"
print(text[0:100]) # 输出:Python(不会报错)
print(text[100:200]) # 输出:(空字符串,不会报错)
3.5 知识体系总览
下面这张图把字符串的四个核心操作串起来了,你看看它们之间的关系:
3.6 操作对比速查表
| 操作 | 语法 | 示例 | 结果 | 性能 |
|---|---|---|---|---|
| 拼接 | + |
"Hello" + " " + "World" |
"Hello World" |
小规模可用 |
| 拼接 | join() |
" ".join(["Hello", "World"]) |
"Hello World" |
大规模推荐 |
| 重复 | * |
"Ha" * 3 |
"HaHaHa" |
高效 |
| 索引 | [n] |
"Python"[0] |
"P" |
O(1) |
| 切片 | [start:stop:step] |
"Python"[0:3] |
"Pyt" |
O(k) |
个人建议:刚开始学的时候,多动手写几个切片例子。我当年就是在交互式环境里反复试,才真正理解 start、stop、step 三个参数是怎么配合的。特别是负步长,光看文档容易晕,跑一遍就明白了。
字符串操作看似简单,但用好了能写出非常优雅的代码。记住:拼接用 join,重复用 *,取单个字符用索引,取子串用切片。这四个操作配合起来,能解决 90% 的字符串处理需求。