首页 游戏 软件 资讯 排行榜 专题
首页
业界动态
你的代码为什么又长又乱?可能是函数没用好

你的代码为什么又长又乱?可能是函数没用好

热心网友
95
转载
2026-04-22

一、概述

每天重复相同的操作,是不是感觉有点枯燥?比如,你每天都要煮饭,得经历洗米、加水、按下煮饭键这三步。如果每次都要从头到尾念叨一遍这个过程,那可就太费劲了。

免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈

别担心,函数就是来拯救你的。在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)  # ❌ 错误:关键字参数后不能再有位置参数

传参有一条铁律:位置参数必须出现在所有关键字参数之前。一旦开始使用关键字参数指定某个变量,后面的所有参数都必须以关键字形式指定。

来源:https://www.51cto.com/article/839747.html
免责声明: 游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

相关攻略

你的代码为什么又长又乱?可能是函数没用好
业界动态
你的代码为什么又长又乱?可能是函数没用好

一、概述 每天重复相同的操作,是不是感觉有点枯燥?比如,你每天都要煮饭,得经历洗米、加水、按下煮饭键这三步。如果每次都要从头到尾念叨一遍这个过程,那可就太费劲了。 别担心,函数就是来拯救你的。在Python的世界里,函数就像一个“一键煮饭”的智能按钮。你只需要把那些重复的步骤打包成一个固定的“命令”

热心网友
04.22
Pandas 精通十:透视表/交叉表实战,复杂数据汇总一键搞定
业界动态
Pandas 精通十:透视表/交叉表实战,复杂数据汇总一键搞定

吃透Pandas两大“数据汇总神器”:透视表与交叉表实战指南 在数据处理的工具箱里,如果说基础的清洗、筛选是基本功,那么多维度、交叉式的数据汇总,往往就是区分新手与熟手的分水岭。面对诸如“按地区加品类统计销售额”、“分析不同省份的商品订单分布”这类需求,如果还停留在手动分组、多层循环的老路上,不仅代

热心网友
04.22
看了 1000 多个 PR 之后,这七个错误每次都出现
业界动态
看了 1000 多个 PR 之后,这七个错误每次都出现

最后 如果你在审阅自己的PR时,也常常撞见上面这些问题,先别急着懊恼。这恰恰说明,你的关注点已经开始从“代码能不能跑通”,转向了“代码能不能长期、稳定地活下去”。而真正扎实的工程能力,往往就是从这一步开始生根发芽的。 做了三年技术负责人,审过的代码评审少说也有几百个。大概在审到第400个左右的时候,

热心网友
04.22
Cursor 3来了!一句话让所有Agent一起干活
AI
Cursor 3来了!一句话让所有Agent一起干活

Cursor 3发布:一个为“Agent编写一切代码”的世界而生的工具 智东西作者|毕伟豪编辑|漠影 智东西4月4日消息,就在昨天凌晨,编程工具Cursor迎来了其第三代版本——Cursor 3的正式发布。官方将其定位为“为一个所有代码都由Agent编写的世界而生”的工具,这句宣言,无疑为整个开发者

热心网友
04.22
AI编程“屎山危机”来了?代码生成过载,人工审核跟不上
AI
AI编程“屎山危机”来了?代码生成过载,人工审核跟不上

▲头图由AI辅助生成 前言:当代码生产进入“涡轮增压”时代 智东西编译 陈佳编辑 程茜 智东西4月7日消息,据《纽约时报》今日报道,一场由AI驱动的“代码洪流”正在席卷软件开发领域。随着Anthropic、OpenAI的新一代编程模型相继亮相,以及像Cursor这样的AI编程工具快速普及,一个矛盾的

热心网友
04.22

最新APP

宝宝过生日
宝宝过生日
应用辅助 04-07
台球世界
台球世界
体育竞技 04-07
解绳子
解绳子
休闲益智 04-07
骑兵冲突
骑兵冲突
棋牌策略 04-07
三国真龙传
三国真龙传
角色扮演 04-07

热门推荐

连亏五个季度后,光伏板块终于盈利了
科技数码
连亏五个季度后,光伏板块终于盈利了

三季报收官,光伏企业交出了近年难得的尚佳成绩 三季报发布完毕,光伏行业总算交出了一份近年来难得的、还算不错的成绩单。市场等这一刻,确实等了挺久。 根据Choice光伏设备板块收录的78家企业财报,整个板块三季度的净利润达到了7 58亿元。这个数字怎么看?不妨对比一下:就在二季度,板块的净亏损还高达4

热心网友
04.22
天龙三号首飞失利:与猎鹰9号对标之路,归零迭代成破局关键
科技数码
天龙三号首飞失利:与猎鹰9号对标之路,归零迭代成破局关键

北京天兵科技天龙三号火箭首飞失利解析 最近,北京天兵科技自主研发的天龙三号大型液体运载火箭,在酒泉卫星发射中心执行首次飞行任务时遭遇失利,这无疑是给国内商业航天关注者带来了一次震动。这款被寄予厚望的火箭,瞄准的是近地轨道20吨级的可回收运力,其设计初衷是通过低成本、高频次的发射模式,抢占一箭36星组

热心网友
04.22
开发者自建48台Mac mini集群,撑起Overcast播客转录
科技数码
开发者自建48台Mac mini集群,撑起Overcast播客转录

苹果芯片实战:48台Mac mini搭建本地AI集群,如何碘伏云端语音识别? 最近科技圈有个挺有意思的消息。知名播客应用Overcast的开发者Marco Arment,自己动手搭了个“大家伙”——一个由48台苹果Mac mini组成的服务器集群。关键是,这个集群没走寻常路,它完全绕开了云端AI服务

热心网友
04.22
领克10+与10全球首秀:高效补能搭配赛道王者,开启纯电高性能新篇
科技数码
领克10+与10全球首秀:高效补能搭配赛道王者,开启纯电高性能新篇

纯电赛道再进化:领克10系列如何重新定义“运动轿车”? 如果问,纯电时代最让人怀念传统燃油车的是什么?很多人会把票投给两件事:说走就走的补能,和随心所欲的操控。最近,领克用一场全球首秀给出了自己的答案。旗下全新的中大型运动轿车领克10,以及更极致的性能版本领克10+联袂登场。这不仅仅是两款新车,更像

热心网友
04.22
Apple Vision Pro新专利曝光:将实现按需定制与组件更换
科技数码
Apple Vision Pro新专利曝光:将实现按需定制与组件更换

苹果正酝酿一款“可自定义”的Vision Pro,核心框架支持模块化拼装 一则来自供应链和专利领域的消息,引起了科技圈的关注。4月8日,有外媒报道指出,苹果似乎并不满足于当前的一体化设计思路,其正在深入探索如何打造一款高度可自定义的Apple Vision Pro。未来的VR AR头显,用户或许能像

热心网友
04.22