当前位置: 首页 > news >正文

Python 函数完全指南:定义与调用

目录

1. 什么是函数?

2. 函数的定义

2.1 基本语法

2.2 带参数的函数

2.3 带返回值的函数

2.4 空函数(占位)

3. 函数的调用

4. 参数类型详解

4.1 位置参数(必须参数)

4.3 关键字参数

4.4 可变长度参数

4.5 参数组合顺序

5. 返回值详解

5.1 单个返回值

5.2 多个返回值(本质是返回元组)

5.3 return 语句省略时返回 None

5.4 return 提前退出函数

6. 作用域

6.1 局部变量与全局变量

6.2 nonlocal 关键字(用于嵌套函数)

7. 函数也是对象

8. 匿名函数(lambda)

9. 递归函数

10. 类型注解(Type Hints)

11. 常见内置函数示例

12.常见陷阱与最佳实践


在编程中,我们经常需要重复执行某段代码。如果每次都复制粘贴,不仅代码冗长,而且修改起来非常麻烦。函数就是解决这个问题的利器:它将一段具有独立功能的代码打包成一个“积木块”,需要时只需“调用”即可。

1. 什么是函数?

函数是一段可重复使用的代码块,它接收输入(参数),进行处理,并可能返回输出(返回值)。函数可以帮你:

  • 避免重复:同样的逻辑只需写一次。

  • 模块化:将复杂程序拆分成小功能块。

  • 易维护:修改函数内部实现,所有调用处自动生效。

Python 内置了很多函数(如print()len()),你也可以自定义函数。

2. 函数的定义

2.1 基本语法

使用def关键字定义函数,后面跟函数名、括号()和冒号:,函数体缩进。

def function_name(parameters):
"""可选的文档字符串"""
函数体代码
return 返回值 # 可选

eg

def greet(): """打印欢迎信息""" print("Hello, welcome to Python!") # 调用函数 greet()
  • def greet():def是定义函数的关键字,greet是函数名,空括号表示该函数不接受任何参数,冒号表示函数体开始。

  • """打印欢迎信息""":这是一个文档字符串(docstring),用三个双引号包围。它是对函数功能的说明,可以通过help(greet)greet.__doc__查看。虽然不是必需的,但强烈建议添加。

  • print("Hello, welcome to Python!"):这是函数体,缩进表示属于函数的一部分。当函数被调用时,这一行代码会被执行。

  • greet():调用函数,执行函数体内的代码。

2.2 带参数的函数

def greet_person(name): """向指定的人打招呼""" print(f"Hello, {name}!") greet_person("Alice") # Hello, Alice!
  • def greet_person(name)::定义了一个形参name,它将在函数内部作为变量使用。

  • print(f"Hello, {name}!"):函数体内使用了name变量,它的值由调用时传入。

  • greet_person("Alice"):调用时传入实参"Alice",它会被赋值给形参name,因此函数体内输出Hello, Alice!

2.3 带返回值的函数

使用return语句返回结果。

def add(a, b): """返回两个数的和""" result = a + b return result sum_val = add(3, 5) # 返回 8 print(sum_val)

代码解析

  • def add(a, b)::定义两个形参ab

  • result = a + b:计算两个参数的和,赋值给局部变量result

  • return result:将result的值返回给调用者。函数执行到return语句时会立即结束,并将返回值传递给调用方。

  • sum_val = add(3, 5):调用add函数,实参35分别传给ab,函数返回8,然后赋值给变量sum_val

  • print(sum_val):输出8

2.4 空函数(占位)

如果函数体还未实现,可以用pass占位。

def not_ready(): pass # 稍后实现

代码解析

  • def not_ready()::定义函数。

  • pass:是一个空语句,什么都不做。语法上需要一个语句,但逻辑上还未实现,用pass避免语法错误。


3. 函数的调用

调用函数就是使用函数名加上括号和实际参数。

# 定义 def multiply(x, y): return x * y # 调用 result = multiply(4, 5) print(result) # 20

代码解析

  • def multiply(x, y)::定义乘法函数。

  • return x * y:返回两数乘积。

  • result = multiply(4, 5):调用函数,实参4对应x5对应y,返回值20存入result

  • print(result):输出20

调用时的细节

  • 函数名后面必须跟括号,即使没有参数也要写()

  • 实参会按照形参的位置一一对应(位置参数)。

  • 调用时传递的实参个数必须与形参个数匹配(除非有默认参数)。

4. 参数类型详解

4.1 位置参数(必须参数)

最普通的形式,调用时按顺序传递。

def greet_with_default(name, greeting="Hello"): print(f"{greeting}, {name}!") greet_with_default("Alice") # Hello, Alice! greet_with_default("Bob", "Hi") # Hi, Bob!

代码解析

  • greeting="Hello":为greeting参数指定默认值"Hello"。调用时若不提供第二个参数,则使用默认值。

  • greet_with_default("Alice"):只传一个参数,greeting使用默认值"Hello",输出Hello, Alice!

  • greet_with_default("Bob", "Hi"):传入两个参数,greeting被覆盖为"Hi",输出Hi, Bob!

注意:默认参数必须放在非默认参数之后。

# 错误写法 def wrong(a=1, b): # SyntaxError pass

陷阱:默认参数的值只在函数定义时计算一次,因此不能使用可变对象作为默认值(如列表)。

# 不推荐 def add_item(item, lst=[]): lst.append(item) return lst print(add_item(1)) # [1] print(add_item(2)) # [1, 2] ← 同一个列表被重复使用

代码解析

  • 因为默认参数lst在函数定义时被创建(一个空列表),之后每次调用若不提供lst,都会使用同一个列表对象,导致累积。

  • 解决办法是使用None作为默认值,然后在函数内部创建新列表。

正确做法

def add_item(item, lst=None): if lst is None: lst = [] lst.append(item) return lst

代码解析

  • lst=None:默认值设为不可变对象None

  • if lst is None: lst = []:每次调用时若未传入列表,则新建一个空列表,保证了独立性。

4.3 关键字参数

调用时通过形参名指定实参,可以改变顺序。

def describe_pet(name, species): print(f"{name} is a {species}") describe_pet(species="cat", name="Tom") # Tom is a cat

代码解析

  • describe_pet(species="cat", name="Tom"):显式指定每个参数的名字,顺序可以与定义不同。这样调用时不会受位置影响,增强了可读性。

4.4 可变长度参数

  • *args:接收任意多个位置参数,打包成元组。

  • **kwargs:接收任意多个关键字参数,打包成字典。

def sum_all(*args): return sum(args) print(sum_all(1, 2, 3, 4)) # 10

代码解析

  • *args:收集所有传入的位置参数为一个元组,这里args(1,2,3,4)

  • sum(args):内置函数sum对元组求和,返回10

def print_info(**kwargs): for key, value in kwargs.items(): print(f"{key}: {value}") print_info(name="Alice", age=30, city="Paris")

代码解析

  • **kwargs:收集所有传入的关键字参数为一个字典,这里kwargs{'name':'Alice','age':30,'city':'Paris'}

  • 遍历字典并打印。

4.5 参数组合顺序

在函数定义中,参数的顺序必须是:

  1. 位置参数

  2. 默认参数

  3. *args

  4. 关键字参数(仅限*之后)

  5. **kwargs

def complex_func(a, b=1, *args, c=2, **kwargs): pass

代码解析

  • a是普通位置参数。

  • b=1是默认参数。

  • *args接收多余的位置参数。

  • c=2是仅限关键字参数(必须通过关键字传递)。

  • **kwargs接收多余的关键字参数。


5. 返回值详解

5.1 单个返回值

def square(x): return x ** 2

代码解析:函数返回x的平方,返回后调用方可以接收。

5.2 多个返回值(本质是返回元组)

def get_stats(numbers): return min(numbers), max(numbers), sum(numbers)/len(numbers) low, high, avg = get_stats([1,2,3,4,5]) print(low, high, avg) # 1 5 3.0

代码解析

  • return min(...), max(...), avg(...):实际上返回了一个元组(min, max, avg)

  • 调用方通过low, high, avg = ...进行拆包,分别接收三个值。

5.3return语句省略时返回None

def do_nothing(): pass print(do_nothing()) # None

代码解析:函数没有显式return,默认返回None

5.4return提前退出函数

def is_positive(n): if n > 0: return True return False

代码解析

  • 如果n > 0,执行return True,函数立即结束,不会执行后面的return False

  • 否则执行return False。这种写法可避免使用else


6. 作用域

6.1 局部变量与全局变量

  • 在函数内部赋值的变量是局部变量,只在函数内有效。

  • 在函数外部定义的变量是全局变量,可在函数内读取,但若要修改需用global关键字。

x = 10 # 全局变量 def func(): global x # 声明要修改全局变量 x = 20 y = 5 # 局部变量 func() print(x) # 20

代码解析

  • x = 10:全局变量。

  • def func():内部global x:告诉 Python 这里的x是全局变量,而不是创建局部变量。

  • x = 20:修改全局x的值为 20。

  • y = 5:未声明global,因此是局部变量,函数外部无法访问。

  • 调用func()后,全局x变为 20。

注意:避免过多使用global,推荐通过参数传递和返回值来通信。

6.2nonlocal关键字(用于嵌套函数)

在内层函数中修改外层函数(非全局)的变量。

def outer(): count = 0 def inner(): nonlocal count count += 1 return count return inner counter = outer() print(counter()) # 1 print(counter()) # 2

代码解析

  • outer函数中定义了局部变量count和内层函数inner

  • inner中使用nonlocal count声明要修改的是外层函数outercount变量,而不是创建一个新的局部变量。

  • count += 1修改外层变量。

  • outer返回inner函数对象,形成一个闭包。每次调用counter()都会增加并返回count的值。


7. 函数也是对象

在 Python 中,函数是一等公民,可以赋值给变量、作为参数传递、作为返回值。

def add(a, b): return a + b my_func = add # 赋值 print(my_func(3, 4)) # 7

代码解析:将函数add赋值给变量my_funcmy_func现在指向同一个函数对象,可以像add一样调用。

def apply(func, x, y): return func(x, y) print(apply(add, 5, 6)) # 11

代码解析apply函数接收一个函数作为参数func,然后在内部调用它。这体现了高阶函数的特性。


8. 匿名函数(lambda)

lambda表达式用于创建简单的、单表达式的匿名函数。

square = lambda x: x ** 2 print(square(5)) # 25

代码解析

  • lambda x: x ** 2定义了一个匿名函数,等价于def square(x): return x**2

  • lambda只能包含一个表达式,不能包含语句。

# 常用于 sort 的 key 参数 pairs = [(1, 'one'), (2, 'two'), (3, 'three')] pairs.sort(key=lambda pair: pair[1]) # 按字符串排序

代码解析sortkey参数接收一个函数,用于从每个元素中提取比较键。这里用lambda取每个元组的第二个元素(字符串)作为排序依据。

限制:lambda 只能有一个表达式,不能包含语句(如printreturn等)。


9. 递归函数

函数调用自身称为递归。需要明确的终止条件。

def factorial(n): if n <= 1: return 1 return n * factorial(n - 1) print(factorial(5)) # 120

代码解析

  • if n <= 1: return 1:递归的终止条件,防止无限递归。

  • return n * factorial(n-1):递归调用,每次减少n的值。

  • 调用过程:factorial(5)5 * factorial(4)5 * 4 * factorial(3)→ ... →5 * 4 * 3 * 2 * 1

注意:Python 递归深度有限制(默认约 1000),深层递归建议改用循环。

10. 类型注解(Type Hints)

Python 3.5+ 支持类型注解,提高代码可读性(不强制检查)。

def greet(name: str) -> str: return f"Hello, {name}"

代码解析

  • name: str:表示参数name应为字符串类型。

  • -> str:表示返回值应为字符串类型。

  • 这些注解只是提示,不会在运行时检查类型错误。可以用mypy工具进行静态类型检查。


11. 常见内置函数示例

  • print():输出

  • len():返回长度

  • type():返回类型

  • input():读取用户输入

  • range():生成整数序列

  • sum()max()min()

这些内置函数无需定义,直接使用。

12.常见陷阱与最佳实践

陷阱说明解决方案
使用可变对象作为默认参数函数多次调用共享同一对象使用None并在函数内创建新对象
在函数内修改全局变量未声明会创建同名局部变量使用global或通过参数/返回值传递
混淆位置参数和关键字参数调用时顺序错误明确指定关键字参数名
递归深度过大导致栈溢出递归超过系统限制改用循环或增加sys.setrecursionlimit
忘记return导致返回None预期有返回值但实际为None检查函数所有分支是否都有return
lambda内使用复杂逻辑无法使用语句,代码难读改用普通函数

感谢你的观看,期待我们下次再见!

http://www.rkmt.cn/news/1424502.html

相关文章:

  • 网页切图工具,网格切图,非常方便
  • 两个独立事件的联合概率
  • 2026年北京老家具回收机构排行 靠谱之选盘点 - 优质品牌商家
  • 千问大模型在阿里生态中的实战应用指南
  • 收藏!Python小白必看:从零入门大模型,手把手带你掌握企业级实战能力
  • 专访 7 名普通职场人:AI 来了之后,你过得还好吗?
  • 告别风扇噪音与高温:FanControl三分钟搞定Windows散热优化
  • 别再死记硬背Sarsa公式了!用Python手搓一个走迷宫AI,5分钟搞懂On-Policy和Q-learning的区别
  • 工业防爆监控技术解析与山东区域选型实践
  • Windows开始菜单修复终极指南:三步恢复消失的磁贴
  • Codex 新增“宠物”功能:不只是可爱,而是一个轻量工作状态提醒器
  • 工具使用、代理和 Voyager 论文
  • 别再被多重共线性坑了!用Python的sklearn手把手教你调岭回归的alpha参数
  • 2026年嵌丝道口板TOP5厂商盘点 品质与实力对比 - 优质品牌商家
  • 93、CAN FD数据链路层核心:帧结构对比与DLC编码革命
  • 172 号卡哪个推荐码是官方一级?10000 置顶权限真实解析 - 172号卡
  • Lindy自动化项目管理:从概念验证到规模化落地的7个关键决策节点(附20年踩坑清单)
  • 2026年5月更新:浙江老爹鞋制造商业内推荐与趋势解析 - 2026年企业资讯
  • Harness 中的请求影子复制:用于离线分析
  • 我的Obsidian知识库,现在可以自动剪藏笔记到本地了
  • 【从零开始的JUC并发第四章】:JUC常用工具类
  • 新手也能跑通大模型,Hugging Face 环境配置与模型加载指南
  • 5分钟掌握VideoDownloadHelper:你的网页视频下载救星
  • 告别LPC!手把手教你用ESPI协议连接PCH与EC(含信号实测图与模式选择指南)
  • 告别格式返工!okbiye 论文智能排版,一键对齐千校规范,毕业季效率拉满
  • GPU内存稳定性实战指南:深入解析MemtestCL系统教程
  • Java程序员快速上手分布式系统必备!
  • 告别Vivado原生编辑器:用VSCode+插件打造你的FPGA高效开发环境(含Verilog语法检查与波形图绘制)
  • 企业搜索升级迫在眉睫!未部署AI搜索的团队正面临37%的信息召回率断崖式下滑(IDC 2024Q2预警)
  • 【多变量输入单步预测】基于霜冰优化算法(RIME)优化CNN-BiLSTM-Attention的风电功率预测研究(Matlab代码实现)