查看: 319|回复: 0

Python字符串split与join分割拼接实战与性能优化

[复制链接]
发表于 2 小时前 | 显示全部楼层 |阅读模式
Python 字符串 split 与 join 是互为逆操作

在 Python 文本处理中,split() 负责把字符串按规则拆成列表,join() 负责把可迭代对象按分隔符拼回字符串。解析 CSV 行、拆分 URL 路径、拼接 SQL、格式化日志、生成 HTML 或路径,都会用到这两个操作。下面按方法、参数、典型场景、常见错误、性能和高级分割来整理。

一、split():默认空白与指定分隔符

不传参数时,split() 会把连续空白符当成一个分隔符,并自动去掉首尾空白;传入指定分隔符时,则按该分隔符严格拆分。
  1. text = 'Python Java Go Rust'
  2. print(text.split())  # ['Python', 'Java', 'Go', 'Rust']
  3. csv_line = '小明,25,北京,工程师'
  4. print(csv_line.split(','))  # ['小明', '25', '北京', '工程师']
  5. multiline = '第一行\n第二行\n第三行'
  6. print(multiline.split('\n'))  # ['第一行', '第二行', '第三行']
复制代码

常见坑是 split() 和 split(' ') 的行为不同:前者合并连续空格,后者严格按每个空格拆分,连续空格会产生空字符串。
  1. text = 'a b c d'
  2. print(text.split())     # ['a', 'b', 'c', 'd']
  3. print(text.split(' '))  # ['a', '', '', 'b', '', 'c', '', '', '', 'd']
  4. text = ',a,b,c,'
  5. print(text.split(','))  # ['', 'a', 'b', 'c', '']
  6. print([x for x in text.split(',') if x])  # ['a', 'b', 'c']
复制代码

二、maxsplit 与 rsplit:限制拆分次数

maxsplit 用于限制拆分次数,rsplit 从右侧开始拆。解析键值对、HTTP 头、命令行参数时,通常只需要按第一个冒号或空格拆一次。
  1. text = 'a-b-c-d-e'
  2. print(text.split('-'))      # ['a', 'b', 'c', 'd', 'e']
  3. print(text.split('-', 1))   # ['a', 'b-c-d-e']
  4. print(text.split('-', 2))   # ['a', 'b', 'c-d-e']
  5. print(text.rsplit('-', 2))  # ['a-b-c', 'd', 'e']
  6. header = 'Content-Type: application/json; charset=utf-8'
  7. key, value = header.split(':', 1)
  8. print(f'键: {key.strip()}')  # 键: Content-Type
  9. print(f'值: {value.strip()}')  # 值: application/json; charset=utf-8
复制代码

三、splitlines():更稳地按行拆分

splitlines() 能处理 \n、\r\n 等换行符,避免直接用 split('\n') 时残留 \r。keepends=True 可以保留行尾换行符。
  1. text = '第一行\n第二行\r\n第三行\n第四行'
  2. print(text.splitlines())
  3. # ['第一行', '第二行', '第三行', '第四行']
  4. print(text.splitlines(keepends=True))
  5. # ['第一行\n', '第二行\r\n', '第三行\n', '第四行']
复制代码

四、partition() 与 rpartition():一刀切三段

partition() 在第一次出现分隔符的位置把字符串切成三部分:分隔符之前、分隔符本身、分隔符之后。找不到分隔符时返回原字符串、空字符串、空字符串。rpartition() 则从右侧开始找。
  1. text = 'Python@Java@Go'
  2. print(text.partition('@'))   # ('Python', '@', 'Java@Go')
  3. print(text.rpartition('@'))  # ('Python@Java', '@', 'Go')
  4. print(text.partition('#'))   # ('Python@Java@Go', '', '')
复制代码

只需要切一次且可能保留分隔符时,partition() 比 split() 更直接。例如解析 URL 协议、邮箱用户名和域名、MySQL 连接字符串。
  1. url = 'https://www.example.com/path?query=value'
  2. protocol, _, rest = url.partition('://')
  3. print(protocol)  # https
  4. print(rest)      # www.example.com/path?query=value
  5. email = 'user@example.com'
  6. local_part, _, domain = email.partition('@')
  7. print(f'用户名: {local_part}')  # 用户名: user
  8. print(f'域名: {domain}')        # 域名: example.com
  9. conn_str = 'mysql://user:password@localhost:3306/dbname'
  10. protocol, _, rest = conn_str.partition('://')
  11. auth, _, server_db = rest.rpartition('@')
  12. user, _, password = auth.partition(':')
  13. server, _, dbname = server_db.partition('/')
  14. print(f'用户: {user}, 密码: {password}, 服务器: {server}, 数据库: {dbname}')
复制代码

选择原则:需要切多次或次数不确定时用 split();确定只切一次时用 partition()。

五、join():把列表拼成字符串

join() 的调用方是分隔符,参数是可迭代对象。所有元素都必须是字符串,否则会抛出 TypeError。
  1. words = ['Python', 'Java', 'Go', 'Rust']
  2. print(', '.join(words))          # Python, Java, Go, Rust
  3. print(''.join(['a', 'b', 'c']))  # abc
  4. print('\n'.join(['第一行', '第二行', '第三行']))
  5. print('\t'.join(['姓名', '年龄', '城市']))
复制代码

非字符串元素需要先转换:
  1. items = ['项目', 1, '测试', 2]
  2. # '-'.join(items)  # TypeError
  3. result = '-'.join(str(item) for item in items)
  4. print(result)  # 项目-1-测试-2
复制代码

六、join() 的典型应用

拼接 SQL 占位符、生成 HTML、拼路径、输出表格都常用 join()。
  1. columns = ['name', 'age', 'city']
  2. placeholders = ', '.join(['%s'] * len(columns))
  3. query = f"INSERT INTO users ({', '.join(columns)}) VALUES ({placeholders})"
  4. print(query)
  5. # INSERT INTO users (name, age, city) VALUES (%s, %s, %s)
复制代码
  1. items = ['苹果', '香蕉', '橘子']
  2. html_list = '<ul>\n' + '\n'.join(f' <li>{item}</li>' for item in items) + '\n</ul>'
  3. print(html_list)
  4. path_parts = ['home', 'user', 'documents', 'report.pdf']
  5. path = '/'.join(path_parts)
  6. print(path)  # home/user/documents/report.pdf
复制代码
  1. data = [
  2.     ['小明', '25', '北京'],
  3.     ['小红', '23', '上海'],
  4.     ['小刚', '26', '广州'],
  5. ]
  6. for row in data:
  7.     print('| ' + ' | '.join(row) + ' |')
复制代码

七、join() 为什么比循环 += 快

在循环中用 + 或 += 拼接大量字符串,会反复分配和复制内存;join() 通常只分配一次内存,因此在列表拼接场景更高效。
  1. import time
  2. words = ['hello'] * 100000
  3. start = time.perf_counter()
  4. result = ''
  5. for word in words:
  6.     result += word
  7. elapsed_plus = time.perf_counter() - start
  8. print(f'用 + 拼接:{elapsed_plus:.4f}秒')
  9. start = time.perf_counter()
  10. result = ''.join(words)
  11. elapsed_join = time.perf_counter() - start
  12. print(f'用 join:{elapsed_join:.4f}秒')
复制代码

原文字段给出的结论是:时间差距可能达到几十倍甚至上百倍。实际项目中,少量拼接用 + 或 f-string 更简洁,大量拼接用列表收集后再 join。

八、split() 与 join() 的组合用法

格式转换、日期标准化、单词倒序都依赖先拆后拼。
  1. csv_data = '小明,25,北京,工程师'
  2. name, age, city, job = csv_data.split(',')
  3. sql = f"INSERT INTO users (name, age, city, job) VALUES ('{name}', {age}, '{city}', '{job}')"
  4. print(sql)
  5. date_slash = '2024/05/30'
  6. date_dash = '-'.join(date_slash.split('/'))
  7. print(date_dash)  # 2024-05-30
  8. sentence = 'I love Python programming'
  9. words = sentence.split()
  10. reversed_sentence = ' '.join(reversed(words))
  11. print(reversed_sentence)  # programming Python love I
复制代码

清理空白和生成 slug 也可以直接用 split() + join():
  1. def normalize_whitespace(text):
  2.     return ' '.join(text.split())
  3. text = 'Hello world\t\tPython \n\n 编程'
  4. print(normalize_whitespace(text))  # Hello world Python 编程
  5. def slugify(text):
  6.     slug = '-'.join(text.lower().split())
  7.     return slug
  8. print(slugify('My First Blog Post'))  # my-first-blog-post
复制代码

矩阵或表格转置同样可以用 split() 拆行、zip() 转置、join() 拼回:
  1. table = [
  2.     '姓名,年龄,城市',
  3.     '小明,25,北京',
  4.     '小红,23,上海',
  5.     '小刚,26,广州',
  6. ]
  7. rows = [row.split(',') for row in table]
  8. transposed = list(zip(*rows))
  9. result = [','.join(col) for col in transposed]
  10. for line in result:
  11.     print(line)
复制代码

九、多分隔符分割与保留分隔符

Python 内置 split() 只支持单个分隔符。多分隔符可以用 replace 后再 split,也可以直接用正则 re.split。若正则中加捕获组,还能保留分隔符。
  1. import re
  2. text = '苹果,香蕉;橘子|葡萄 西瓜'
  3. result = text.replace(';', ',').replace('|', ',').replace(' ', ',').split(',')
  4. print(result)
  5. result = re.split(r'[,;| ]', text)
  6. print(result)
  7. result = re.split(r'([,;| ])', text)
  8. print(result)
复制代码

保留分隔符在分句场景很有用,例如按句末标点切分并保留标点:
  1. import re
  2. text = 'Hello, World! How are you?'
  3. result = re.split(r'([,.!? ])', text)
  4. result = [s for s in result if s and s != ' ']
  5. print(result)
  6. def split_sentences(text):
  7.     parts = re.split(r'([。!?.!?])', text)
  8.     sentences = []
  9.     for i in range(0, len(parts) - 1, 2):
  10.         sentences.append(parts[i] + parts[i + 1])
  11.     if len(parts) % 2 == 1 and parts[-1]:
  12.         sentences.append(parts[-1])
  13.     return sentences
  14. text = '你好!今天天气不错。你吃饭了吗?'
  15. print(split_sentences(text))
复制代码

十、实战:手写 CSV 行解析与 csv 模块

标准 split(',') 不能处理引号内的逗号,例如 小明,"北京,朝阳区",25。手写解析器需要记录是否处于引号内,只在非引号状态下遇到分隔符才切分。实际项目更推荐直接用 csv 模块。
  1. def parse_csv_line(line, delimiter=',', quote_char='"'):
  2.     fields = []
  3.     current_field = ''
  4.     in_quotes = False
  5.     for char in line:
  6.         if char == quote_char:
  7.             in_quotes = not in_quotes
  8.         elif char == delimiter and not in_quotes:
  9.             fields.append(current_field)
  10.             current_field = ''
  11.         else:
  12.             current_field += char
  13.     fields.append(current_field)
  14.     return fields
  15. csv_line = '小明,"北京,朝阳区",25,工程师'
  16. fields = parse_csv_line(csv_line)
  17. print(fields)  # ['小明', '北京,朝阳区', '25', '工程师']
  18. import csv
  19. reader = csv.reader([csv_line])
  20. print(next(reader))  # ['小明', '北京,朝阳区', '25', '工程师']
复制代码

十一、性能与最佳实践

只需要切一次时,partition() 找到第一个分隔符就停止,比 split() 更合适;需要切多次时用 split()。
  1. text = 'key: value with many colons: extra data'
  2. key, value = text.split(':', 1)
  3. key, _, value = text.partition(':')
复制代码

拼接策略可以按数据量选择:
  1. name = '小明'
  2. greeting = '你好,' + name + '!'
  3. greeting = f'你好,{name}!'
  4. words = ['Python', 'Java', 'Go', 'Rust']
  5. result = ', '.join(words)
  6. lines = []
  7. for i in range(1000):
  8.     lines.append(f'第{i}行')
  9. result = '\n'.join(lines)
复制代码

核心结论:split() 把字符串转列表,rsplit() 从右拆,splitlines() 按换行拆,partition() 和 rpartition() 返回三元组,join() 把列表拼成字符串。需要切多次用 split(),只切一次用 partition(),大量字符串拼接优先用 join(),多分隔符分割用 re.split()。split() 与 join() 互为逆操作,组合起来就能完成大量文本解析、清洗、格式转换和结构化输出任务。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-9-11 17:18 , Processed in 0.023096 second(s), 18 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部