上一篇我们学会了 “if 判断” 和 “循环”—— 能写出有逻辑的代码了,但如果遇到 “需要重复用某段代码” 的场景(比如多次计算长方形面积、反复验证用户输入),每次都复制粘贴会很麻烦。而 “函数” 就是解决这个问题的 “神器”:把常用代码封装成 “可重复调用的工具”,用的时候喊个名字就能用,不用重复写。今天用生活案例讲透函数的定义、调用、参数和返回值,新手也能快速上手。

一、先搞懂:什么是函数?用生活案例类比

生活中到处都是 “函数” 的影子:

  1. 计算器:你输入 “数字 + 运算”(比如 3+5),它返回结果(8)—— 这是 “有输入、有输出的函数”;
  2. 洗衣机:你按下 “启动键”(不用输入额外内容),它自动完成 “加水→洗衣→脱水”(不用管中间步骤)—— 这是 “无输入、有动作的函数”;
  3. 手电筒:你按 “开关”(输入 “开 / 关”),它执行 “亮 / 灭”(有输入、有动作无返回)—— 这是 “有输入、无输出的函数”。

在 Python 里,函数就是 “一段封装好的代码块”,具有 3 个核心特点:

  1. 可重复调用:定义一次,后续想用时直接喊函数名,不用重复写代码;
  2. 可接收输入:根据需要给函数传 “原材料”(参数),让函数处理不同数据;
  3. 可返回结果:函数处理完后,能把结果 “交回来”(返回值),供后续代码使用。

二、函数的基础用法:定义→调用(两步搞定)

用函数的核心流程只有两步:先定义(造工具)再调用(用工具)。就像先造一台计算器(定义函数),之后每次算东西都用这台计算器(调用函数)。

1. 第一步:定义函数(造工具)

语法格式(注意缩进!):

def 函数名(参数列表):  # def定义函数的关键字,参数列表可空(没原材料)

    """函数说明文档(可选,用来解释函数作用,按Ctrl+Q能看到)"""

    函数体  # 要封装的代码(必须缩进,推荐4个空格)

    return 返回值  # 可选,用来返回处理结果(没返回值时可省略)

关键规则:
  1. 函数名:和变量名规则一样(字母 / 数字 / 下划线,不数字开头,见名知意),推荐用 “蛇形命名法”(比如calculate_areagreet_user);
  2. 参数列表:如果函数需要 “原材料”,就写在这里(多个参数用逗号分隔),不需要就空着(括号不能省);
  3. 函数说明文档:用三引号包裹,说明函数作用、参数含义、返回值,新手也要养成写的习惯,方便后续自己看;
  4. return:如果需要函数 “交结果”,就用return,没写的话函数默认返回None(空值)。
案例 1:定义一个 “打招呼” 的函数(无参数、无返回值)

比如每次运行都打印 “你好,欢迎学习 Python!”,不用传参数,也不用返回结果:

def greet():

    """无参数,无返回值,功能:打印打招呼信息"""

    print("你好,欢迎学习Python")

    print("今天也要加油呀~")  # 函数体可以有多行代码

案例 2:定义一个 “计算长方形面积” 的函数(有参数、有返回值)

需要传入 “长” 和 “宽”(参数),计算后返回面积(返回值):

def calculate_rect_area(length, width):

    """

    计算长方形面积

    参数:

        length: 长方形的长(数值型)

        width: 长方形的宽(数值型)

    返回值:

        area: 长方形的面积(length * width

    """

    area = length * width  # 函数体:计算面积

    return area  # 返回结果(把area交给调用者)

2. 第二步:调用函数(用工具)

定义好函数后,想用时直接写 “函数名 (参数)” 即可,就像按计算器的 “计算键”。

案例 1:调用 “打招呼” 函数(无参数)

无参数的函数,调用时括号里什么都不用写:

# 调用greet函数(执行函数体里的打印代码)

greet()

# 可以重复调用,不用再写print语句

greet()

运行结果:

你好,欢迎学习Python

今天也要加油呀~

你好,欢迎学习Python

今天也要加油呀~

案例 2:调用 “计算长方形面积” 函数(有参数、接收返回值)

有参数的函数,调用时要传对应参数,返回值可以用变量接收:

# 调用函数,传入长=5,宽=3,用变量area1接收返回值

area1 = calculate_rect_area(5, 3)

print(f"长方形1的面积:{area1}")  # 输出:长方形1的面积:15

# 重复调用,传入不同参数(长=10,宽=4

area2 = calculate_rect_area(10, 4)

print(f"长方形2的面积:{area2}")  # 输出:长方形2的面积:40

注意:函数必须 “先定义,再调用”

Python 代码是 “从上到下顺序执行” 的,如果先调用再定义,会报错 “函数未定义”:

# 错误示例:调用在定义前面

greet()  # 报错:NameError: name 'greet' is not defined

def greet():

    print("你好")

三、函数的参数:给函数传 “原材料”(重点)

参数是函数的 “原材料入口”,不同场景需要传不同类型的参数。Python 里最常用的参数类型有 4 种:位置参数、关键字参数、默认参数、不定长参数,逐个拆解。

1. 位置参数:按 “顺序” 传参(最基础)

调用函数时,参数的 “顺序” 必须和定义时一致,个数也要对应,否则会算错或报错。

案例:定义一个 “计算两数之和与差” 的函数

def calculate_sum_diff(a, b):

    """

    计算两数的和与差

    参数:

        a: 第一个数(位置参数1

        b: 第二个数(位置参数2

    返回值:

        sum_ab: 和(a + b

        diff_ab: 差(a - b

    """

    sum_ab = a + b

    diff_ab = a - b

    return sum_ab, diff_ab  # 函数可以返回多个值,用逗号分隔

调用时按顺序传参:

# 位置参数:a=10b=5(顺序不能乱)

sum_result, diff_result = calculate_sum_diff(10, 5)

print(f"和:{sum_result},差:{diff_result}")  # 输出:和:15,差:5

# 错误示例1:顺序传反(a=5b=10),结果错了

sum_wrong, diff_wrong = calculate_sum_diff(5, 10)

print(f"错误和:{sum_wrong},错误差:{diff_wrong}")  # 输出:错误和:15,错误差:-5

# 错误示例2:参数个数不匹配(少传1个)

# calculate_sum_diff(10)  # 报错:TypeError: calculate_sum_diff() missing 1 required positional argument: 'b'

2. 关键字参数:按 “名字” 传参(不怕顺序乱)

调用函数时,明确指定 “参数名 = 值”,这样不用记顺序,适合参数多的场景。

案例:调用上面的calculate_sum_diff函数

# 关键字参数:明确a=10b=5,顺序可以换

sum1, diff1 = calculate_sum_diff(a=10, b=5)

print(f"关键字传参1:和={sum1},差={diff1}")  # 输出:和=15,差=5

# 顺序换了也没问题(因为指定了参数名)

sum2, diff2 = calculate_sum_diff(b=5, a=10)

print(f"关键字传参2:和={sum2},差={diff2}")  # 输出:和=15,差=5

混合使用:位置参数在前,关键字参数在后

可以先传位置参数,再传关键字参数,但位置参数不能在关键字参数后面

# 正确:先位置参数a=10,再关键字参数b=5

sum3, diff3 = calculate_sum_diff(10, b=5)

print(f"混合传参:和={sum3},差={diff3}")  # 输出:和=15,差=5

# 错误:位置参数在关键字参数后面

# calculate_sum_diff(a=10, 5)  # 报错:SyntaxError: positional argument follows keyword argument

3. 默认参数:给参数设 “默认值”(调用时可省)

定义函数时,给参数设置 “默认值”,调用时如果不传这个参数,就用默认值;传了就用新值。适合 “大部分情况用默认值,偶尔需要改” 的场景。

案例:定义一个 “计算折扣价” 的函数

比如大部分商品打 95 折(默认折扣 0.95),VIP 客户打 8 折(传折扣 0.8):

def calculate_discount_price(original_price, discount=0.95):

    """

    计算商品折扣价

    参数:

        original_price: 原价(必须传,无默认值)

        discount: 折扣(默认0.95,可选传)

    返回值:

        discount_price: 折扣价(原价 * 折扣)

    """

    discount_price = original_price * discount

    return discount_price

调用时的 3 种情况:

# 情况1:只传原价(用默认折扣0.95

price1 = calculate_discount_price(100)  # 原价100,折扣0.95

print(f"普通客户价:{price1}")  # 输出:普通客户价:95.0

# 情况2:传原价和折扣(覆盖默认值)

price2 = calculate_discount_price(100, 0.8)  # 原价100,折扣0.8

print(f"VIP客户价1{price2}")  # 输出:VIP客户价180.0

# 情况3:用关键字参数传折扣(更清晰)

price3 = calculate_discount_price(original_price=100, discount=0.7)

print(f"VIP客户价2{price3}")  # 输出:VIP客户价270.0

注意:默认参数要放在 “非默认参数后面”

定义函数时,有默认值的参数必须在没默认值的参数后面,否则报错:

# 错误示例:默认参数在非默认参数前面

# def calculate_discount_price(discount=0.95, original_price):  # 报错:SyntaxError: non-default argument follows default argument

4. 不定长参数:接收 “不确定个数” 的参数(灵活)

如果不知道要传多少个参数(比如计算 “任意多个数的总和”),用不定长参数*args(接收多个位置参数,存成元组)和**kwargs(接收多个关键字参数,存成字典)。

案例 1:用*args计算任意多个数的总和

def calculate_total(*args):

    """

    计算任意多个数的总和

    参数:

        *args: 不定长位置参数(接收多个数值,存成元组)

    返回值:

        total: 所有数的总和

    """

    print(f"接收的参数:{args}")  # 查看args的类型(元组)

    total = sum(args)  # sum()Python内置函数,能直接求和

    return total

调用时传任意个数的参数:

# 2个数

total1 = calculate_total(10, 20)

print(f"2个数的和:{total1}")  # 输出:接收的参数:(10, 20)2个数的和:30

# 5个数

total2 = calculate_total(1, 2, 3, 4, 5)

print(f"5个数的和:{total2}")  # 输出:接收的参数:(1, 2, 3, 4, 5)5个数的和:15

# 传列表(需要在列表前加*,把列表元素拆成位置参数)

num_list = [100, 200, 300]

total3 = calculate_total(*num_list)

print(f"列表元素的和:{total3}")  # 输出:接收的参数:(100, 200, 300),列表元素的和:600

案例 2:用**kwargs接收任意多个关键字参数

比如处理用户的 “个人信息”,可能有姓名、年龄、电话等不确定的字段:

def print_user_info(**kwargs):

    """

    打印用户的任意个人信息

    参数:

        **kwargs: 不定长关键字参数(接收多个键值对,存成字典)

    """

    print(f"用户信息(字典):{kwargs}")  # 查看kwargs的类型(字典)

    for key, value in kwargs.items():  # 遍历字典,打印每个字段

        print(f"{key}{value}")

调用时传任意个关键字参数:

# 2个关键字参数

print_user_info(name="小明", age=18)

# 输出:

# 用户信息(字典):{'name': '小明', 'age': 18}

# name:小明

# age18

# 3个关键字参数

print_user_info(name="小红", age=20, phone="13812345678")

# 输出:

# 用户信息(字典):{'name': '小红', 'age': 20, 'phone': '13812345678'}

# name:小红

# age20

# phone13812345678

# 传字典(需要在字典前加**,把字典拆成关键字参数)

user_dict = {"name": "小刚", "age": 19, "address": "北京"}

print_user_info(**user_dict)

# 输出:

# 用户信息(字典):{'name': '小刚', 'age': 19, 'address': '北京'}

# name:小刚

# age19

# address:北京

四、函数的返回值:让函数 “交结果”(return 用法)

返回值是函数处理后的 “输出”,用return关键字实现。新手要注意 3 个核心点:return的作用、返回多个值、return后的代码不执行。

1. return的基础作用:返回结果 + 终止函数

def add(a, b):

    result = a + b

    return result  # 返回结果,同时终止函数

    print("这句代码不会执行!")  # return后面的代码永远跑不到

接收返回值:用变量存起来,供后续使用

sum_result = add(3, 5)

print(f"3+5的结果:{sum_result}")  # 输出:3+5的结果:8

2. 函数可以返回多个值(用逗号分隔)

返回多个值时,Python 会自动把它们打包成 “元组”,接收时可以用多个变量 “解包”:

def calculate(a, b):

    sum_ab = a + b

    diff_ab = a - b

    product_ab = a * b  #

    quotient_ab = a / b  #

    return sum_ab, diff_ab, product_ab, quotient_ab  # 返回4个值

接收多个返回值:

# 4个变量接收(个数要和返回值一致)

sum_r, diff_r, product_r, quotient_r = calculate(10, 2)

print(f"和:{sum_r},差:{diff_r},积:{product_r},商:{quotient_r}")

# 输出:和:12,差:8,积:20,商:5.0

# 用一个变量接收(会变成元组)

result_tuple = calculate(10, 2)

print(f"返回的元组:{result_tuple}")  # 输出:返回的元组:(12, 8, 20, 5.0)

3. 没有return的函数:默认返回None

如果函数里没写return,调用后会得到None(空值),常用于 “只做动作不返回结果” 的函数:

def print_hello():

    print("Hello!")  # 只有打印动作,没return

# 调用函数,用变量接收返回值

result = print_hello()

print(f"函数返回值:{result}")  # 输出:Hello!,函数返回值:None

五、函数嵌套:函数里套函数(复杂逻辑拆分)

就像 “洗衣机里有加水、洗衣、脱水的小模块”,函数里也能定义函数(嵌套函数),用来拆分复杂逻辑,让代码更清晰。

案例:计算 “两个数的平均值”,拆分成 “求和→求平均” 两个步骤

def calculate_average(a, b):

    """计算两个数的平均值(外层函数)"""

    # 定义嵌套函数:计算两数之和

    def add_numbers(x, y):

        return x + y  # 嵌套函数的返回值

   

    # 调用嵌套函数(只能在outer函数里调用,外面用不了)

    total = add_numbers(a, b)

    # 计算平均值

    average = total / 2

    return average

调用外层函数:

avg1 = calculate_average(10, 20)

print(f"1020的平均值:{avg1}")  # 输出:1020的平均值:15.0

avg2 = calculate_average(5, 15)

print(f"515的平均值:{avg2}")  # 输出:515的平均值:10.0

# 错误:嵌套函数不能在外面调用

# add_numbers(10, 20)  # 报错:NameError: name 'add_numbers' is not defined

六、新手易错点总结

  1. 函数调用在定义前面

Python 从上到下执行,必须先写def 函数名(),再写函数名()调用,否则报错 “函数未定义”。

  1. 参数个数不匹配

定义时写了 2 个参数,调用时只传 1 个,会报错missing 1 required positional argument;传多了会报错takes 2 positional arguments but 3 were given

  1. 默认参数位置错误

定义函数时,有默认值的参数必须放在没默认值的参数后面(比如def func(a, b=1)正确,def func(b=1, a)错误)。

  1. return 后面的代码不执行

return不仅返回结果,还会终止函数,所以return后面的代码永远跑不到,别在后面写逻辑。

  1. 嵌套函数的作用域问题

嵌套函数(内层函数)只能在 “定义它的外层函数” 里调用,外面调用会报错(作用域只在外部函数内)。

  1. *args**kwargs的拆包问题

传列表给*args时,要加*(比如func(*list));传字典给**kwargs时,要加**(比如func(**dict)),否则会把整个列表 / 字典当成一个参数。

七、练手小任务(动手巩固!)

  1. 任务 1:定义一个 “判断闰年” 的函数

规则:能被 4 整除但不能被 100 整除,或能被 400 整除的年份是闰年。

要求:函数接收 1 个参数(年份),返回True(是闰年)或False(不是闰年),并写说明文档。

  1. 任务 2:定义一个 “计算列表平均值” 的函数

要求:函数接收 1 个参数(列表,元素是数值),返回列表的平均值(总和 / 元素个数),如果列表为空,返回None并提示 “列表为空”。

  1. 任务 3:用*args定义一个 “找最大值” 的函数

要求:函数接收任意多个数值参数,返回其中的最大值(不用max()内置函数,自己用循环实现)。

  1. 任务 4:定义一个 “生成个人名片” 的函数(用**kwargs

要求:函数接收任意多个关键字参数(比如namejobcompanyphone),返回一个字符串名片,格式如下:

姓名:小明

职位:Python开发

公司:XX科技

电话:13812345678

下一篇我们会讲 “Python 基础语法 4:列表与字典”,详细讲解这两个最常用的 “数据容器”—— 列表用来存 “有序的多个数据”(比如购物清单),字典用来存 “键值对数据”(比如用户信息),它们和函数搭配使用,能实现更复杂的功能。如果练手时遇到问题,评论区留言,我会帮你分析解决!

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐