你的代码为什么又长又乱?可能是函数没用好
一、概述
每天重复相同的操作,是不是感觉有点枯燥?比如,你每天都要煮饭,得经历洗米、加水、按下煮饭键这三步。如果每次都要从头到尾念叨一遍这个过程,那可就太费劲了。
免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈
别担心,函数就是来拯救你的。在Python的世界里,函数就像一个“一键煮饭”的智能按钮。你只需要把那些重复的步骤打包成一个固定的“命令”,下次需要时,轻轻调用一下,一切就搞定了。
今天,我们就来聊聊怎么定义函数、传递参数和接收返回值。掌握了这些,你的代码就能彻底告别“复制粘贴”的蛮荒时代,迈入“优雅复用”的文明阶段。

二、知识点讲解
1. 函数的定义与调用
万事开头难,咱们先从最简单的开始。定义函数的语法是 def,后面跟上函数名和一对括号。
# 定义函数
def greet():
print(“你好,我是 OpenClaw!”)
# 调用函数
greet() # 输出: 你好,我是 OpenClaw!
greet() # 多次调用
看,定义了一个叫 greet 的函数,它只做一件事:打印一句问候。调用它就像喊它的名字,喊一次,它就工作一次。
2. 带参数:让函数更灵活
只会说同一句话可不够,我们需要函数能“因人而异”。这就得请出参数了。
# 单个参数
def greet(name):
print(f“你好,{name}!”)
greet(“小明”) # 输出: 你好,小明!
greet(“小红”) # 输出: 你好,小红!
# 多个参数
def add(a, b):
result = a + b
print(f“{a} + {b} = {result}”)
add(3, 5) # 输出: 3 + 5 = 8
# 关键字参数(更清晰)
def introduce(name, age, city):
print(f“我叫{name},今年{age}岁,来自{city}”)
introduce(age=25, city=“北京”, name=“张三”) # 顺序无所谓
从固定问候到个性化问候,只需要一个参数。多个参数让函数能力更强,而关键字参数则让代码意图一目了然,即便参数顺序打乱也不影响。
3. 返回值:函数的“产出”
函数不能光干活不“交差”,return 语句就是用来交付成果的。
# 使用 return 返回结果
def add(a, b):
return a + b
result = add(3, 5)
print(result) # 输出: 8
# 可以返回多个值(实际是元组)
def get_stats(numbers):
total = sum(numbers)
a verage = total / len(numbers)
return total, a verage # 返回元组
s, a vg = get_stats([10, 20, 30])
print(f“总和: {s}, 平均: {a vg}”) # 总和: 60, 平均: 20.0
# 提前返回
def find_first_even(nums):
for n in nums:
if n % 2 == 0:
return n # 找到就返回
return None # 没找到
print(find_first_even([1, 3, 5, 7])) # None
print(find_first_even([1, 3, 4, 7])) # 4
return 不仅能返回一个值,还能返回多个(打包成元组)。更妙的是,它支持“提前返回”,一旦任务完成就能立刻退出,提升效率。
4. 参数默认值
有些参数我们希望它有“保底选项”,这时候默认值就派上用场了。
# 默认参数
def greet(name, greeting=“你好”):
print(f“{greeting},{name}!”)
greet(“小明”) # 输出: 你好,小明!
greet(“小明”, “早上好”) # 输出: 早上好,小明!
greet(“小明”, greeting=“晚上好”) # 输出: 晚上好,小明!
# ⚠️ 重要:默认参数要放最后
# 错误: def func(a=1, b) # SyntaxError!
# 正确: def func(b, a=1)
记住一个关键规则:默认参数必须放在所有非默认参数的后面,否则解释器会“懵掉”。
5. *args 和 **kwargs:不定参数
你永远不知道用户会传入多少个参数?没关系,*args 和 **kwargs 这种“收纳神器”就是为此而生。
# *args:接收任意数量的位置参数(变成元组)
def sum_all(*args):
print(args) # (1, 2, 3, 4)
return sum(args)
print(sum_all(1, 2, 3, 4)) # 10
# **kwargs:接收任意数量的关键字参数(变成字典)
def print_info(**kwargs):
print(kwargs) # {‘name’: ‘小明’, ‘age’: 25}
print_info(name=“小明”, age=25)
# 组合使用
def func(*args, **kwargs):
print(“位置参数:”, args)
print(“关键字参数:”, kwargs)
func(1, 2, 3, name=“test”, age=20)
# 输出:
# 位置参数: (1, 2, 3)
# 关键字参数: {‘name’: ‘test’, ‘age’: 20}
简单来说,一个星号*搞定任意位置参数(变成元组),两个星号**搞定任意关键字参数(变成字典)。两者组合,几乎能应对所有传参场景。
6. 变量的作用域
代码世界也分“地盘”。变量在哪儿定义,决定了它在哪儿能被访问。
# 全局变量 vs 局部变量
global_var = “我是全局变量”
def test():
local_var = “我是局部变量”
print(global_var) # 可以访问全局变量
print(local_var) # 可以访问局部变量
test()
# print(local_var) # 报错!局部变量外面访问不到
# ⚠️ 修改全局变量要用 global
counter = 0
def increment():
global counter # 声明要修改全局变量
counter += 1
print(f“计数: {counter}”)
increment() # 计数: 1
increment() # 计数: 2
局部变量“生于函数,死于函数”,外部无法触及。如果想在函数内部修改全局变量,必须用 global 关键字明确声明。这是初学者常踩的坑。
7. 文档字符串(Docstring)
好的代码不仅自己能看懂,还要让别人(包括三个月后的自己)也能看懂。给函数写个简短的说明书吧,这就是文档字符串。
def calculate_area(width, height):
”“”
计算矩形面积
参数:
width: 宽度
height: 高度
返回:
面积(宽 * 高)
”“”
return width * height
# 查看文档
help(calculate_area)
print(calculate_area.__doc__)
用三引号包裹的描述,不仅清晰明了,还能通过 help() 函数直接查看,是专业代码的标配。
三、实战案例
1. 案例:个人记账本
光说不练假把式。我们来用函数打造一个简易的个人记账本,看看它们是如何协同工作的。
# === 账本数据 ===
transactions = [] # 存储 (日期, 类型, 金额, 说明)
# === 函数定义 ===
def add_income(date, amount, description):
”“”添加收入”“”
transactions.append((date, “收入”, amount, description))
print(f“✅ 已添加收入: {date} +{amount}元 ({description})”)
def add_expense(date, amount, description):
”“”添加支出”“”
transactions.append((date, “支出”, amount, description))
print(f“❌ 已添加支出: {date} -{amount}元 ({description})”)
def get_balance():
”“”计算余额”“”
total_income = sum(t[2] for t in transactions if t[1] == “收入”)
total_expense = sum(t[2] for t in transactions if t[1] == “支出”)
return total_income - total_expense
def show_transactions():
”“”显示所有交易记录”“”
if not transactions:
print(“? 暂无记录”)
return
print(“\n” + “=“*50)
print(f“{‘日期’:<12} {‘类型’:<6} {‘金额’:<10} {‘说明’}”)
print(“-“*50)
for date, type_, amount, desc in transactions:
sign = “+” if type_ == “收入” else “-”
print(f“{date:<12} {type_:<6} {sign}{amount:<9} {desc}”)
print(“-“*50)
print(f“? 当前余额: {get_balance()}元”)
print(“=“*50 + “\n”)
def get_stats():
”“”统计报表”“”
income = sum(t[2] for t in transactions if t[1] == “收入”)
expense = sum(t[2] for t in transactions if t[1] == “支出”)
print(“\n? 本月统计报表”)
print(f“ 总收入: {income}元”)
print(f“ 总支出: {expense}元”)
print(f“ 结余: {income - expense}元”)
if income > 0:
print(f“ 储蓄率: {(income - expense) / income * 100:.1f}%”)
print()
# === 使用演示 ===
print(“=== 个人记账本 ===\n”)
# 添加几笔记录
add_income(“2026-03-30”, 15000, “工资”)
add_expense(“2026-03-31”, 3000, “房租”)
add_expense(“2026-03-31”, 500, “餐饮”)
add_income(“2026-04-01”, 800, “兼职”)
add_expense(“2026-04-02”, 200, “交通”)
# 查看所有记录
show_transactions()
# 查看统计
get_stats()
# 查看余额
print(f“? 当前余额: {get_balance()}元”)
2. 运行结果:
=== 个人记账本 ===
✅ 已添加收入: 2026-03-30 +15000元 (工资)
❌ 已添加支出: 2026-03-31 -3000元 (房租)
❌ 已添加支出: 2026-03-31 -500元 (餐饮)
✅ 已添加收入: 2026-04-01 +800元 (兼职)
❌ 已添加支出: 2026-04-02 -200元 (交通)
==================================================
日期 类型 金额 说明
--------------------------------------------------
2026-03-30 收入 +15000 工资
2026-03-31 支出 -3000 房租
2026-03-31 支出 -500 餐饮
2026-04-01 收入 +800 兼职
2026-04-02 支出 -200 交通
--------------------------------------------------
? 当前余额: 12100元
==================================================
? 本月统计报表
总收入: 15800元
总支出: 3700元
结余: 12100元
储蓄率: 76.6%
? 当前余额: 12100元
瞧,通过几个功能明确的函数,一个结构清晰、易于维护的记账本就成型了。每项功能独立封装,修改或扩展都非常方便。
四、常见坑点
理论懂了,实战练了,最后再来扫清几个常见的“雷区”。
? 坑点1:修改可变默认参数
# 错误示例:默认参数是可变对象
def add_item(item, items=[]):
items.append(item)
return items
print(add_item(“a”)) # [‘a’]
print(add_item(“b”)) # [‘a’, ‘b’](应该是 [‘b’]!)
# 正确做法:用 None 做默认值
def add_item(item, items=None):
if items is None:
items = []
items.append(item)
return items
print(add_item(“a”)) # [‘a’]
print(add_item(“b”)) # [‘b’]
记住,函数的默认参数在定义时就会被计算并保存。如果默认值是列表、字典这种可变对象,所有调用都可能共享同一个对象,导致意外修改。最佳实践是使用 None 作为默认值,在函数内部初始化。
? 坑点2:return 和 print 混淆
# 错误示例:用 print 代替 return
def add(a, b):
print(a + b) # 只是打印,没有返回值
result = add(3, 5)
print(result) # None(没有返回值!)
# 正确做法
def add(a, b):
return a + b
result = add(3, 5)
print(result) # 8
print 是把内容输出到屏幕给人看,而 return 是把结果传递给程序中的其他代码。这是两个完全不同的操作,千万别搞混了。
? 坑点3:参数传递是引用还是拷贝?
# 列表作为参数(可变对象)
def modify_list(lst):
lst.append(4) # 修改了原列表
nums = [1, 2, 3]
modify_list(nums)
print(nums) # [1, 2, 3, 4](原列表被修改!)
# 如果不想修改原列表
def modify_list_safe(lst):
new_list = lst.copy() # 复制一份
new_list.append(4)
return new_list
nums = [1, 2, 3]
result = modify_list_safe(nums)
print(nums) # [1, 2, 3](原列表不变)
print(result) # [1, 2, 3, 4]
在Python中,对于列表、字典这类可变对象,函数参数传递的是“引用”(或者说内存地址)。这意味着,在函数内部修改它们,会直接影响外部的原始数据。如果不想改变原数据,务必先做一份拷贝。
? 坑点4:位置参数和关键字参数混用顺序
# 错误示例
def func(a, b, c):
print(a, b, c)
func(1, c=3, b=2) # ✅ 正确:位置参数在前
# func(a=1, 2, c=3) # ❌ 错误:关键字参数后不能再有位置参数
传参有一条铁律:位置参数必须出现在所有关键字参数之前。一旦开始使用关键字参数指定某个变量,后面的所有参数都必须以关键字形式指定。
相关攻略
从零到一:用AI生成一份专业的媒体影响力报告 但凡在内容或运营团队待过的人,大概都对制作《媒体影响力报告》这类活儿记忆犹新。那过程,堪称一场跨部门接力赛:运营同事得先从各个平台后台手动扒拉数据,计算阅读量、粉丝增长和互动率;拿到一堆冰冷数字后,还得拉着账号负责人反复琢磨定位和文案;最后,抱着半成品火
封面新闻记者 邹阿江 图由航空工业成飞提供 2026年“五一”国际劳动节前夕,航空工业成飞的技术专家聂海平,荣获了一枚全国五一劳动奖章。 消息传来,身边同事都说,“大师”拿奖是实至名归。可聂海平自己呢,还是那副老样子——摆摆手,说自己不过是个普通人,幸运地站在一个好平台上,干着点自己感兴趣的事儿罢了
编辑 | 王凤枝 “AI时代,每天干3个小时就足够了。” 这句话出自前亚马逊资深工程师、技术大牛史蒂夫·雅吉(Steve Yegge)之口,算得上是对当前AI狂热的一剂清醒剂。 当整个行业都在为“10倍提效”而欢呼雀跃时,雅吉却点出了一个被普遍忽视的代价:在AI的高强度辅助下,程序员的产出固然爆炸式
一、概述 每天重复相同的操作,是不是感觉有点枯燥?比如,你每天都要煮饭,得经历洗米、加水、按下煮饭键这三步。如果每次都要从头到尾念叨一遍这个过程,那可就太费劲了。 别担心,函数就是来拯救你的。在Python的世界里,函数就像一个“一键煮饭”的智能按钮。你只需要把那些重复的步骤打包成一个固定的“命令”
吃透Pandas两大“数据汇总神器”:透视表与交叉表实战指南 在数据处理的工具箱里,如果说基础的清洗、筛选是基本功,那么多维度、交叉式的数据汇总,往往就是区分新手与熟手的分水岭。面对诸如“按地区加品类统计销售额”、“分析不同省份的商品订单分布”这类需求,如果还停留在手动分组、多层循环的老路上,不仅代
热门专题
热门推荐
峡谷区域唯一唱片需集齐三个碎片合成。首个碎片位于地图西北角木箱木桶旁,外观如跳动火焰。集齐碎片可解锁新内容并提升游戏体验,探索时留意细节可能发现更多隐藏惊喜。
《遥遥西土》中,西土唱片需集齐三个碎片合成。首个碎片位于地图东南角的管子洞内,获取过程简单,无复杂谜题或战斗。整体流程清晰,玩家按指引收集全部碎片即可合成唱片,轻松完成收集任务。
《鸣潮》联动《赛博朋克:边缘行者》,推出五星角色露西与丽贝卡,可通过限定卡池与活动免费获取。联动包含专属剧情、夜之城风格场景及高难度BOSS战,并植入动画经典音乐。参与预热活动和完成剧情任务可获得限定奖励,全方位打造沉浸式赛博朋克体验。
鼻噶流”玩法围绕“混沌爪牙”基因展开,开局以小体型角色灵活发育,注重走位与策略而非堆叠体型与伤害。该玩法在较高难度下提供了与传统平推思路不同的趣味体验,适合追求新鲜操作感的玩家尝试。
《异环》S级气态弧盘“好狗狗走四方”可提升充能与全队攻击,适合早雾等辅助。完成主线任务“成交?成交!”后解锁番外副本“月光当铺”,首次击败BOSS墨菲克斯即可免费获取。战斗时建议中距离拉扯,优先清理小狼,搭配破韧与输出角色更易通关。





