一、前置核心概念:Python 函数返回值的本质
1.1 三大返回类型
Python 中所有函数都有返回值 (无显式return或return后无值的函数,默认返回None),按使用场景可分为三类:
| 类型 | 核心特征 | 典型函数 |
|---|---|---|
| 返回新对象 | 不修改原输入对象,生成并返回全新对象 | sorted()、str.upper()、list() |
| 原地操作(返回 None) | 修改原输入对象,无新对象生成,返回None |
list.sort()、list.reverse()、dict.update() |
| 有条件 / 特定返回值 | 既可能修改原对象,也可能返回特定值(如长度、状态码) | list.pop()、file.write()、os.mkdir() |
1.2 设计逻辑:为什么有的函数原地操作,有的返回新对象?
- 可变对象(list/dict/set) :提供原地操作以节省内存 (无需复制整个对象),同时提供返回新对象的替代函数(如
sort()vssorted())以满足保留原对象的需求; - 不可变对象(str/tuple/int/float/datetime) :因不可修改,所有操作均返回新对象;
- 易用性权衡 :链式调用必须依赖返回新对象的函数(如
sorted(lst).reverse()),而原地操作更适合无需保留原对象的场景。
二、内置函数分类解析(覆盖 95%+ 常用函数)
2.1 序列操作类:核心对比sort/sorted、reverse/reversed
序列操作是最易混淆返回值的场景,重点对比原地操作 与返回新对象的函数对:
2.1.1 列表(list)操作函数
| 函数 | 返回值 | 操作方式 | 适用类型 | 代码示例 |
|---|---|---|---|---|
list.sort() |
None |
原地排序 | 仅list |
lst = [3,1,2]; lst.sort() → lst = [1,2,3] |
sorted() |
新list |
非原地排序 | 所有可迭代对象 | lst = [3,1,2]; sorted(lst) → [1,2,3](原lst不变) |
list.reverse() |
None |
原地反转 | 仅list |
lst = [1,2,3]; lst.reverse() → lst = [3,2,1] |
reversed() |
反转迭代器 | 非原地反转 | 所有可迭代对象 | lst = [1,2,3]; list(reversed(lst)) → [3,2,1](原lst不变) |
list.append() |
None |
原地添加元素 | 仅list |
lst = [1,2]; lst.append(3) → lst = [1,2,3] |
list.extend() |
None |
原地扩展列表 | 仅list |
lst = [1,2]; lst.extend([3,4]) → lst = [1,2,3,4] |
list + list |
新list |
非原地合并 | 仅list |
[1,2] + [3,4] → [1,2,3,4](原列表不变) |
list.pop() |
被删除元素 | 原地删除元素 | 仅list |
lst = [1,2,3]; lst.pop() → 3,原lst = [1,2] |
del list[idx] |
None |
原地删除元素 | 仅list |
lst = [1,2]; del lst[0] → lst = [2] |
list.clear() |
None |
原地清空列表 | 仅list |
lst = [1,2]; lst.clear() → lst = [] |
代码验证:sort vs sorted 的本质区别
# 原地操作:sort()修改原列表,返回None
lst1 = [5, 2, 8, 1]
result1 = lst1.sort()
print(f"sort()后原列表:{lst1}") # [1, 2, 5, 8]
print(f"sort()返回值:{result1}") # None
# 返回新对象:sorted()保留原列表,返回新列表
lst2 = [5, 2, 8, 1]
result2 = sorted(lst2)
print(f"\nsorted()后原列表:{lst2}") # [5, 2, 8, 1]
print(f"sorted()返回值:{result2}") # [1, 2, 5, 8]
2.1.2 字符串(str)操作函数
字符串是不可变类型,所有操作均返回新对象,无原地操作函数:
| 函数 | 返回值 | 功能 | 代码示例 |
|---|---|---|---|
str.upper() |
新str |
转大写 | "hello".upper() → "HELLO" |
str.lower() |
新str |
转小写 | "HELLO".lower() → "hello" |
str.replace() |
新str |
替换字符 | "abc".replace("a","x") → "xbc" |
str.split() |
新list |
分割字符串 | "a b c".split() → ["a","b","c"] |
str.strip() |
新str |
去除首尾空白 | " abc ".strip() → "abc" |
易错点:字符串方法不会修改原字符串
s = "hello"
s.upper() # 无返回值接收,原字符串不变
print(s) # "hello"
# 正确用法:接收返回值
s = s.upper()
print(s) # "HELLO"
2.1.3 元组(tuple)操作函数
元组是不可变类型,仅支持查询类操作,返回新对象或特定值:
| 函数 | 返回值 | 功能 |
|---|---|---|
tuple.index() |
元素索引 | 查找元素位置 |
tuple.count() |
元素个数 | 统计元素出现次数 |
tuple + tuple |
新tuple |
合并元组 |
tuple(lst) |
新tuple |
列表转元组 |
2.2 字典(dict)操作函数
字典是可变类型,提供原地操作与返回新对象的双重函数:
| 函数 | 返回值 | 操作方式 | 代码示例 |
|---|---|---|---|
dict.update() |
None |
原地更新字典 | d = {"a":1}; d.update({"b":2}) → d = {"a":1,"b":2} |
dict.copy() |
新dict |
浅拷贝字典 | d = {"a":1}; d.copy() → {"a":1}(原字典不变) |
dict.pop() |
被删除 value | 原地删除键值对 | d = {"a":1}; d.pop("a") → 1,原d = {} |
dict.popitem() |
被删除(key,value) |
原地删除最后一个键值对 | d = {"a":1,"b":2}; d.popitem() → ("b",2) |
dict.clear() |
None |
原地清空字典 | d = {"a":1}; d.clear() → d = {} |
dict.get() |
value 或默认值 | 查询键值对 | d = {"a":1}; d.get("b", 0) → 0 |
dict.keys() |
键的视图对象 | 无修改 | d.keys() → dict_keys(['a', 'b']) |
dict.values() |
值的视图对象 | 无修改 | 同上 |
dict.items() |
键值对视图对象 | 无修改 | 同上 |
代码验证:update vs copy
d1 = {"name": "Alice", "age": 20}
d2 = {"age": 21, "city": "Beijing"}
# 原地更新:update()修改d1,返回None
result = d1.update(d2)
print(f"update()后d1:{d1}") # {"name": "Alice", "age": 21, "city": "Beijing"}
print(f"update()返回值:{result}") # None
# 返回新对象:copy()创建新字典
d3 = d1.copy()
print(f"\ncopy()后d3:{d3}") # {"name": "Alice", "age": 21, "city": "Beijing"}
d3["age"] = 22 # 修改新字典不影响原字典
print(f"修改d3后d1:{d1}") # {"name": "Alice", "age": 21, "city": "Beijing"}
2.3 文件操作类函数
文件操作函数的返回值与 IO 操作的本质相关:
| 函数 | 返回值 | 功能 |
|---|---|---|
open() |
文件对象 | 打开文件 |
file.read() |
读取的内容 | 读取文件 |
file.readline() |
一行内容 | 读取一行 |
file.readlines() |
内容列表 | 读取所有行 |
file.write() |
写入的字节数 | 写入文件 |
file.writelines() |
None |
写入多行 |
file.close() |
None |
关闭文件 |
代码验证:write 的返回值
with open("test.txt", "w") as f:
bytes_written = f.write("Hello, Python!")
print(f"写入的字节数:{bytes_written}") # 14
2.4 数学与转换类函数
所有数学与转换类函数均返回新对象或计算结果:
| 函数 | 返回值 | 功能 |
|---|---|---|
int()/float()/str() |
转换后的对象 | 类型转换 |
abs()/round()/max()/min() |
计算结果 | 数学计算 |
sum() |
总和 | 序列求和 |
len() |
长度 | 序列长度 |
type() |
对象类型 | 查询类型 |
id() |
内存地址 | 查询内存地址 |
三、常用标准库函数解析
3.1 os 模块函数
os 模块用于操作系统交互,返回值与操作的本质相关:
| 函数 | 返回值 | 功能 |
|---|---|---|
os.getcwd() |
当前目录路径 | 获取当前工作目录 |
os.listdir() |
文件列表 | 列出目录内容 |
os.path.exists() |
bool |
检查路径是否存在 |
os.path.isfile() |
bool |
检查是否为文件 |
os.path.isdir() |
bool |
检查是否为目录 |
os.mkdir() |
None |
创建目录 |
os.rmdir() |
None |
删除空目录 |
os.remove() |
None |
删除文件 |
os.rename() |
None |
重命名文件 / 目录 |
3.2 sys 模块函数
sys 模块用于 Python 解释器交互:
| 函数 | 返回值 | 功能 |
|---|---|---|
sys.argv |
命令行参数列表 | 获取命令行参数 |
sys.getrefcount() |
引用计数 | 获取对象引用计数 |
sys.exit() |
None |
退出程序 |
sys.path |
模块搜索路径列表 | 获取模块搜索路径 |
3.3 re 模块函数
re 模块用于正则表达式匹配,所有匹配类函数均返回匹配结果或 None:
| 函数 | 返回值 | 功能 |
|---|---|---|
re.match() |
匹配对象或None |
从字符串开头匹配 |
re.search() |
匹配对象或None |
搜索整个字符串 |
re.findall() |
匹配结果列表 | 返回所有匹配结果 |
re.sub() |
替换后的字符串 | 替换匹配内容 |
re.split() |
分割后的列表 | 分割字符串 |
3.4 datetime 模块函数
datetime 对象是不可变类型,所有操作均返回新 datetime 对象:
| 函数 | 返回值 | 功能 |
|---|---|---|
datetime.now() |
当前 datetime 对象 | 获取当前时间 |
datetime.date() |
date 对象 | 获取日期 |
datetime.time() |
time 对象 | 获取时间 |
datetime.strftime() |
格式化字符串 | 时间转字符串 |
datetime.timedelta() |
timedelta 对象 | 时间差 |
四、最易混淆函数对的深度对比
4.1 list.sort() vs sorted()
| 维度 | list.sort() | sorted() |
|---|---|---|
| 返回值 | None |
新list |
| 操作方式 | 原地 | 非原地 |
| 适用类型 | 仅list |
所有可迭代对象(tuple/str/set/dict.keys () 等) |
| 内存效率 | 高(无需复制) | 低(需复制整个对象) |
| 链式调用 | 不支持 | 支持(如sorted(lst).reverse()) |
支持链式调用的示例:
# sorted()返回新列表,可直接调用reverse()
lst = [3,1,2,5,4]
result = list(reversed(sorted(lst))) # 先排序→再反转→转列表
print(result) # [5,4,3,2,1]
4.2 list.reverse() vs reversed()
| 维度 | list.reverse() | reversed() |
|---|---|---|
| 返回值 | None |
反转迭代器 |
| 操作方式 | 原地 | 非原地 |
| 适用类型 | 仅list |
所有可迭代对象 |
| 内存效率 | 高 | 极高(仅返回迭代器,无复制) |
4.3 list.append() vs list + list
| 维度 | list.append() | list + list |
|---|---|---|
| 返回值 | None |
新list |
| 操作方式 | 原地 | 非原地 |
| 功能 | 添加单个元素 | 合并两个列表 |
| 内存效率 | 高 | 低 |
五、易错点与最佳实践
5.1 常见易错点
-
原地操作后赋值给变量:
lst = [3,1,2] sorted_lst = lst.sort() # 错误!sorted_lst为None # 正确: lst.sort() sorted_lst = lst -
字符串方法忘记接收返回值:
s = "hello" s.replace("e", "a") # 错误!原字符串不变 # 正确: s = s.replace("e", "a") -
混淆 reverse () 与 reversed ():
lst = [1,2,3] reversed_lst = lst.reverse() # 错误!None # 正确: reversed_lst = list(reversed(lst))
5.2 最佳实践
- 保留原对象→用返回新对象的函数 :如
sorted()、str.replace()、dict.copy(); - 无需保留原对象→用原地操作的函数 :如
list.sort()、list.reverse()、dict.update(),节省内存; - 链式调用→用返回新对象的函数 :如
sorted(lst).reverse()、"abc".upper().split(); - 明确返回值类型 :调用函数前先确认其返回值类型,避免
None导致的后续错误。
六、全量函数返回值总结表格
6.1 内置序列函数
| 函数 | 返回类型 | 操作方式 |
|---|---|---|
list.sort() |
None |
原地 |
sorted() |
新list |
非原地 |
list.reverse() |
None |
原地 |
reversed() |
迭代器 | 非原地 |
list.append() |
None |
原地 |
list.extend() |
None |
原地 |
list.pop() |
元素 | 原地 |
str.upper() |
新str |
非原地 |
str.split() |
新list |
非原地 |
6.2 内置字典函数
| 函数 | 返回类型 | 操作方式 |
|---|---|---|
dict.update() |
None |
原地 |
dict.copy() |
新dict |
非原地 |
dict.pop() |
值 | 原地 |
dict.get() |
值 / 默认值 | 非原地 |
6.3 标准库常用函数
| 模块 | 函数 | 返回类型 |
|---|---|---|
os |
os.getcwd() |
路径字符串 |
os |
os.mkdir() |
None |
re |
re.findall() |
匹配列表 |
re |
re.sub() |
替换后字符串 |
datetime |
datetime.now() |
datetime 对象 |
七、结语
理解 Python 函数的返回值类型,是写出安全、高效、可维护代码的基础。核心原则是:
- 不可变对象的所有操作均返回新对象;
- 可变对象提供原地操作(返回 None)与返回新对象的双重选择;
- 优先根据「是否需要保留原对象」选择函数类型,再考虑性能与易用性。
通过本文的系统梳理与对比,希望你能彻底解决函数返回值的困惑,避免常见的使用陷阱。