跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像AI 生图工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Python算法

Python 函数基础语法与使用详解

Python 函数是重复使用的代码片段,用于封装逻辑。通过 def 定义,调用时传入实参匹配形参。支持返回值、默认参数及关键字参数。变量分为局部与全局作用域,递归需设定结束条件防止栈溢出。链式与嵌套调用增强灵活性。

PgDevote发布于 2026/3/28更新于 2026/7/2935 浏览
Python 函数基础语法与使用详解

1. 函数是什么

编程中的函数和数学中的函数有一定的相似之处。

  • 数学上的函数,比如 y = sin x,x 取不同的值,y 就会得到不同的结果。
  • 编程中的函数,是一段可以被重复使用的代码片段。

示例一:求数列的和,不使用函数

# 1. 求 1 - 100 的和
sum = 0
for i in range(1, 101):
    sum += i
print(sum)

# 2. 求 300 - 400 的和
sum = 0
for i in range(300, 401):
    sum += i
print(sum)

# 3. 求 1 - 1000 的和
sum = 0
for i in range(1, 1001):
    sum += i
print(sum)

可以发现,这几组代码基本是相似的,只有一点点差异。可以把重复代码提取出来,做成一个函数。

实际开发中,复制粘贴是一种不太好的策略。实际开发的重复代码可能存在几十份甚至上百份。一旦这个重复代码需要被修改,那就得改几十次,非常不便于维护。

示例二:求数列的和(使用函数)

# 定义函数
def calcSum(beg, end):
    sum = 0
    for i in range(beg, end + 1):
        sum += i
    print(sum)

# 调用函数
calcSum(1, 100)
calcSum(300, 400)
calcSum(1, 1000)

可以明显看到,重复的代码已经被消除了。

2. 语法格式

创建函数 / 定义函数

def 函数名 (形参列表):
    函数体
    return 返回值

调用函数 / 使用函数

函数名 (实参列表)  # 不考虑返回值
返回值 = 函数名 (实参列表)  # 考虑返回值
  • 函数定义并不会执行函数体内容,必须要调用才会执行。调用几次就会执行几次
def test1():
    print('hello')
# 如果光是定义函数,而不调用,则不会执行。
  • 函数必须先定义,再使用。
test3()  # 还没有执行到定义,就先执行调用了,此时就会报错。
def test3():
    print('hello')

3. 函数参数

在函数定义的时候,可以在 () 中指定'形式参数'(简称:形参),然后在调用的时候,由调用者把'实际参数'(简称:实参)传递进去。

这样就可以做到一份函数,针对不同的数据进行计算处理。

代码示例

def calcSum(beg, end):
    sum = 0
    for i in range(beg, end + 1):
        sum += i
    print(sum)

calcSum(1, 100)
calcSum(300, 400)
calcSum(1, 1000)

在这个例子里:

  • beg 和 end 是函数的形参
  • 1, 100 / 300, 400 是函数的实参

当执行 calcSum(1, 100) 时,相当于 beg = 1,end = 100,函数内部就可以针对 1-100 进行运算。

当执行 calcSum(300, 400) 时,相当于 beg = 300,end = 400,函数内部就可以针对 300-400 进行运算。

实参和形参之间的关系,就像签合同一样:

  • 形参是合同里的'甲方'、'乙方',是占位符
  • 实参是具体签约的公司或个人,是实际的值

注意:

  • 一个函数可以有一个形参,也可以有多个形参,也可以没有形参。
  • 一个函数的形参有几个,那么传递实参的时候也得传几个,保证个数要匹配。
def test(a, b, c):
    print(a, b, c)

test(10)  # 报错:缺少 2 个必要的位置参数 'b' 和 'c'

报错信息如下:

TypeError: test() missing 2 required positional arguments: 'b' and 'c'
  • 和 C++ / Java 不同,Python 是动态类型的编程语言,函数的形参不必指定参数类型。换句话说,一个函数可以支持多种不同类型的参数。
def test(a):
    print(a)

test(10)
test('hello')
test(True)

运行结果如下:[图片]

4. 函数返回值

函数的参数可以视为函数的'输入',函数的返回值则是函数的'输出'。

我们可以把函数想象成一个工厂:

  • 函数的参数就是原材料
  • 函数的返回值就是生产出的产品

写法一:函数内部直接打印

def calcSum(beg, end):
    sum = 0
    for i in range(beg, end + 1):
        sum += i
    print(sum)

calcSum(1, 100)

运行结果如下:[图片]

写法二:返回结果,由调用者处理

def calcSum(beg, end):
    sum = 0
    for i in range(beg, end + 1):
        sum += i
    return sum

result = calcSum(1, 100)
print(result)

运行结果如下:[图片]

原则上,我们一般倾向于第二种写法,因为它遵循'逻辑和用户交互分离'的编程原则。

  • 第一种写法把计算逻辑和打印交互耦合在一起,后续如果需要把结果保存到文件或通过网络发送,就很难适配。
  • 第二种写法只专注计算逻辑,不负责交互,更容易搭配不同的用户交互代码,实现不同效果。
  • 一个函数可以有多个 return 语句
# 判断是否上奇数
def isOdd(num):
    if num % 2 == 0:
        return False
    else:
        return True

result = isOdd(10)
print(result)

运行结果如下:[图片]

  • 执行到 return 语句,函数会立即结束
def isOdd(num):
    if num % 2 == 0:
        return False
    return True

result = isOdd(10)
print(result)

如果 num 是偶数,进入 if 之后触发 return False,就不会继续执行 return True。

运行结果如下:[图片]

  • 一个函数是可以一次返回多个返回值的。可以使用 , 来分割多个返回值。
def getPoint():
    x = 10
    y = 20
    return x, y

a, b = getPoint()
print(a, b)

运行结果如下:[图片]

  • 如果只想关注其中的部分返回值,可以使用 _ 来忽略不想要的返回值。
def getPoint():
    x = 10
    y = 20
    return x, y

_, b = getPoint()

运行结果如下:[图片]

5. 变量作用域

观察以下代码

def getPoint():
    x = 10
    y = 20
    return x, y

x, y = getPoint()

在这个代码中,函数内部存在 x, y,函数外部也有 x, y。 但是这两组 x, y 不是相同的变量,而只是恰好有一样的名字。

  • 变量只能在所在的函数内部生效。

在函数 getPoint() 内部定义的 x, y 只是在函数内部生效。一旦出了函数的范围,这两个变量就不再生效了。

def getPoint():
    x = 10
    y = 20
    return x, y

getPoint()
print(x, y)

报错:

NameError: name 'x' is not defined
  • 在不同的作用域中,允许存在同名的变量。

虽然名字相同,实际上是不同的变量。

x = 20
def test():
    x = 10
    print(f'函数内部 x = {x}')

test()
print(f'函数外部 x = {x}')

运行结果如下:[图片]

注意:

  • 在函数内部的变量,也称为'局部变量'。
  • 不在任何函数内部的变量,也称为'全局变量'。
  • 如果函数内部尝试访问的变量在局部不存在,就会尝试去全局作用域中查找
x = 20
def test():
    print(f'x = {x}')

test()

运行结果如下:[图片]

  • 如果是想在函数内部,修改全局变量的值,需要使用 global 关键字声明
x = 20
def test():
    global x
    x = 10
    print(f'函数内部 x = {x}')

test()
print(f'函数外部 x = {x}')

运行结果如下:[图片]

如果此处没有 global,则函数内部的 x = 10 就会被视为是创建一个局部变量 x,这样就和全局变量 x 不相关了。

  • if / while / for 等语句块不会影响到变量作用域

换而言之,在 if / while / for 中定义的变量,在语句外面也可以正常使用。

for i in range(1, 10):
    print(f'函数内部 i = {i}')

print(f'函数外部 i = {i}')

运行结果如下:[图片]

6. 函数执行过程

  • 调用函数才会执行函数体代码,不调用则不会执行。
  • 函数体执行结束(或者遇到 return 语句),则回到函数调用位置,继续往下执行。

代码示例:

def test():
    print("执行函数内部代码")
    print("执行函数内部代码")
    print("执行函数内部代码")
    print("1111")

test()
print("2222")
test()
print("3333")

运行结果如下:[图片]

这个过程还可以使用 PyCharm 自带的调试器来观察。

  • 点击行号右侧的空白,可以在代码中插入断点。
  • 右键,选择 Debug,可以按照调试模式执行代码。每次执行到断点,程序都会暂停下来。
  • 使用 Step Into (F7) 功能可以逐行执行代码。

7. 链式调用

代码示例:

# 判定是否是奇数
def isOdd(num):
    if num % 2 == 0:
        return False
    else:
        return True

result = isOdd(10)
print(result)

实际上也可以进行简化:

print(isOdd(10))

运行结果如下:[图片]

把一个函数的返回值,作为另一个函数的参数,这种操作称为链式调用。这是一种比较常见的写法。

8. 嵌套调用

函数内部还可以调用其他的函数,这个动作称为'嵌套调用'。

代码示例:

def test():
    print("执行函数内部代码")
    print("执行函数内部代码")
    print("执行函数内部代码")
    test()

test 函数内部调用了 print 函数,这里就属于嵌套调用。

运行结果如下:[图片]

一个函数里面可以嵌套调用任意多个函数。函数嵌套的过程是非常灵活的。

代码示例:

def a():
    print("函数 a")

def b():
    print("函数 b")
    a()

def c():
    print("函数 c")
    b()

def d():
    print("函数 d")
    c()

d()

运行结果如下:[图片]

如果把代码稍微调整,打印结果则可能发生很大变化。

def a():
    print("函数 a")

def b():
    a()
    print("函数 b")

def c():
    b()
    print("函数 c")

def d():
    c()
    print("函数 d")

d()

运行结果如下:[图片]

注意:上述代码的执行顺序,可以通过画图的方式来理解。

函数之间的调用关系,在 Python 中会使用一个特定的数据结构来表示,称为函数调用栈。每次函数调用,都会在调用栈里新增一个元素,称为栈帧。

可以通过 PyCharm 调试器看到函数调用栈和栈帧。在调试状态下,PyCharm 左下角一般就会显示出函数调用栈。

在这里插入图片描述

每个函数的局部变量,都包含在自己的栈帧中。代码示例:

def a():
    num1 = 10
    print("函数 a")

def b():
    num2 = 20
    a()
    print("函数 b")

def c():
    num3 = 30
    b()
    print("函数 c")

def d():
    num4 = 40
    c()
    print("函数 d")

d()

选择不同的栈帧,就可以看到各自栈帧中的局部变量。如下所示:[图片]

思考:上述代码,a, b, c, d 函数中的局部变量名各不相同。如果变量名是相同的,比如都是 num,那么这四个函数中的 num 是属于同一个变量,还是不同变量呢?

答案:是不同的变量。即使四个函数中都使用相同的变量名 num,它们仍然是完全独立的变量,互不影响。

9. 函数递归

递归是嵌套调用中的一种特殊情况,即一个函数嵌套调用自己。

代码示例:递归计算 5!

def factor(n):
    if n == 1:
        return 1
    return n * factor(n - 1)

result = factor(5)
print(result)

运行结果如下:[图片]

上述代码中,就属于典型的递归操作。在 factor 函数内部,又调用了 factor 自身。

注意:递归代码务必要保证

  • 存在递归结束条件。比如 if n == 1 就是结束条件,当 n 为 1 的时候,递归就结束了。
  • 每次递归的时候,要保证函数的实参是逐渐逼近结束条件的。

如果上述条件不能满足,就会出现'无限递归',这是一种典型的代码错误。

def factor(n):
    return n * factor(n - 1)

result = factor(5)
print(result)

报错:

RecursionError: maximum recursion depth exceeded

如前面所描述,函数调用时会在函数调用栈中记录每一层函数调用的信息。

但是函数调用栈的空间不是无限大的。如果调用层数太多,就会超出栈的最大范围,导致出现问题。

递归的优点:

  • 递归类似于'数学归纳法',明确初始条件和递推公式,就可以解决一系列的问题。
  • 递归代码往往代码量非常少。

递归的缺点:

  • 递归代码往往难以理解,很容易超出掌控范围。
  • 递归代码容易出现栈溢出的情况。
  • 递归代码往往可以转换成等价的循环代码,并且通常来说循环版本的代码执行效率要略高于递归版本。

实际开发的时候,使用递归要慎重!

10. 参数默认值

Python 中的函数,可以给形参指定默认值。带有默认值的参数,可以在调用的时候不传参。

代码示例:计算两个数字的和

def add(x, y, debug=False):
    if debug:
        print(f'调试信息:x={x}, y={y}')
    return x + y

print(add(10, 20))
print(add(10, 20, True))

运行结果如下:[图片]

此处 debug=False 即为参数默认值。当我们不指定第三个参数的时候,默认 debug 的取值即为 False。

注意:带有默认值的参数需要放到没有默认值的参数的后面。

错误代码示例:

def add(x, debug=False, y):
    if debug:
        print(f'调试信息:x={x}, y={y}')
    return x + y

print(add(10, 20))

报错:

SyntaxError: non-default argument follows default argument

11. 关键字参数

在调用函数的时候,需要给函数指定实参。一般默认情况下是按照形参的顺序,来依次传递实参的。

但是我们也可以通过 关键字参数,来调整这里的传参顺序,显式指定当前实参传递给哪个形参。

def test(x, y):
    print(f'x = {x}')
    print(f'y = {y}')

test(x=10, y=20)
test(y=100, x=200)

运行结果如下:[图片]

形如上述 test(x=10, y=20) 这样的操作,即为关键字参数。

小结

函数是编程语言中的一个核心语法机制。Python 中的函数和大部分编程语言中的函数功能都是基本类似的。

我们当下最关键要理解的主要就是三个点:

  • 函数的定义
  • 函数的调用
  • 函数的参数传递

在后续的编程中,会广泛的使用到函数,所以需要反复加深对于函数的理解。

目录

  1. 1. 函数是什么
  2. 1. 求 1 - 100 的和
  3. 2. 求 300 - 400 的和
  4. 3. 求 1 - 1000 的和
  5. 定义函数
  6. 调用函数
  7. 2. 语法格式
  8. 如果光是定义函数,而不调用,则不会执行。
  9. 3. 函数参数
  10. 4. 函数返回值
  11. 判断是否上奇数
  12. 5. 变量作用域
  13. 6. 函数执行过程
  14. 7. 链式调用
  15. 判定是否是奇数
  16. 8. 嵌套调用
  17. 9. 函数递归
  18. 10. 参数默认值
  19. 11. 关键字参数
  20. 小结
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Magic API:低代码接口开发平台完全指南
  • 前端地图开发:地理编码与逆地理编码实战
  • 基于 Spring Boot 的在线考试系统设计与实现——学生课程实践记录
  • TCP 拥塞控制:AIMD 算法深度解析
  • JDBC 连接 Oracle 数据库的常见连接串格式
  • 云开发 Copilot:AI 赋能的低代码开发实践
  • 昇腾 NPU 部署与测评 CodeLlama-7b-Python 模型
  • 分治算法实战:快速排序与荷兰国旗问题详解
  • 本地部署 Wan2.1 视频生成模型全攻略
  • GitHub Copilot Agent 实战指南与体验心得
  • GitHub 上值得参考的量化交易开源项目
  • MIT 室内场景识别数据集介绍与模型训练实战
  • JDK 27 引入后量子混合密钥交换,应对量子计算威胁
  • 基于 FPGA 的神经网络模型设计与实现:手写数字识别
  • AI 并非前端与 UI 的终结者,而是效率提升的加速器
  • 基于 Python 与 Selenium 的大麦网自动抢票脚本实现
  • 基于 UniApp 与 ThinkPHP 的跨平台应用开发实践
  • ComfyUI 节点式工作流与 AI 图像生成技术指南
  • LLaMA-Factory 命令行工具使用指南
  • LangChain 聊天模型多场景实战:从固定角色到合规客服

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • curl 转代码

    解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online