掌握函数的基本结构后,本篇集中梳理位置参数、关键字参数、默认参数、可变参数、打包与解包,并说明 return 的执行规则。
本篇目录
5. 参数的传递方式
6. 可变参数
7. 参数的打包与解包
8. 函数的返回值
5. 参数的传递方式
5.1 位置参数
位置参数按照实参出现的位置,与形参从左到右依次对应。
def user_info(name, age): print(f"姓名:{name}") print(f"年龄:{age}")user_info("张三", 18)位置参数的顺序和数量必须符合函数定义,否则可能传错数据或抛出 TypeError。
5.2 关键字参数
关键字参数使用 形参名=实参值 的形式传递,因此不受书写顺序影响。
def person_info(name, age, city): print(f"姓名:{name},年龄:{age},城市:{city}")person_info(age=25, name="小红", city="上海")person_info(city="广州", age=30, name="小李")位置参数和关键字参数可以混用,但位置参数必须写在关键字参数前面:
def student_info(name, age, gender): print(name, age, gender)student_info("张三", age=18, gender="男")student_info("李四", gender="女", age=20)同一个参数不能重复传值:
# "张三" 已经传给 name,再写 name="李四" 会报错# student_info("张三", name="李四", age=18, gender="男")5.3 默认参数
定义函数时可以提前给参数设置默认值。调用时不传该参数,就使用默认值;主动传值,则覆盖默认值。
def student_info(name, age, gender="男"): print(f"姓名:{name}") print(f"年龄:{age}") print(f"性别:{gender}")student_info("张三", 18) # gender 使用默认值student_info("李四", 20, "女") # 覆盖默认值student_info("王五", 22, gender="女")在普通参数列表中,没有默认值的参数必须放在有默认值参数之前:
def func(a, b=10): print(a, b)# 下面的定义不合法:# def func(a=10, b):# passprint() 就使用了多个默认参数:
print("Python", "Java") # 默认 sep=" "print("Python", "Java", sep=" | ") # 修改分隔符print("不换行", end="") # 修改结束字符print(",继续输出")• sep=" ":多个输出值之间默认使用空格分隔。
• end="\n":输出结束后默认追加换行符。
5.4 仅限位置参数:/
函数定义中,/ 前面的参数只能通过位置传递,不能写成关键字参数。
def func(a, b, /, c, d): print(a, b, c, d)func(10, 20, 30, 40)func(10, 20, c=30, d=40)# a、b 不能使用关键字传递# func(a=10, b=20, c=30, d=40)5.5 仅限关键字参数:*
函数定义中,单独出现的 * 表示它后面的参数只能通过关键字传递。
def func(e, f, *, g, h): print(e, f, g, h)func(10, 20, g=30, h=40)func(10, 20, h=40, g=30)# g、h 不能使用位置传递# func(10, 20, 30, 40)5.6 混合限制
def func(a, b, /, c, d, *, e, f): print(a, b, c, d, e, f)# a、b:只能按位置传递# c、d:位置或关键字均可# e、f:只能按关键字传递func(10, 20, 30, 40, e=50, f=60)func(10, 20, c=30, d=40, e=50, f=60)可以使用一句口诀记忆:
/ 前面只能按位置传递* 后面只能按关键字传递中间两种方式都可以
6. 可变参数
当函数无法提前确定会收到多少个参数时,可以使用可变参数。
6.1 *args:接收任意多个位置参数
*args 会把所有额外的位置参数打包成一个元组。
def show_args(*args): print(args) print(type(args))show_args() # ()show_args(10) # (10,)show_args(1, 2, "Python", True) # (1, 2, "Python", True)args 只是约定俗成的名称,真正产生打包效果的是 *:
def sum_numbers(*numbers): total = 0 for number in numbers: total += number return totalprint(sum_numbers())print(sum_numbers(1, 2))print(sum_numbers(1, 2, 3, 4, 5))6.2 **kwargs:接收任意多个关键字参数
**kwargs 会把所有额外的关键字参数打包成一个字典。
def show_user(**kwargs): print(kwargs) print(type(kwargs)) for key, value in kwargs.items(): print(f"{key} = {value}")show_user()show_user(name="张三", age=18, gender="男")show_user(city="上海", job="老师", salary=8000)kwargs 是 keyword arguments 的缩写,同样只是常见命名,真正产生效果的是 **。
6.3 多种参数组合
常见组合如下:
def func(name, age=18, *args, **kwargs): print("name:", name) print("age:", age) print("args:", args) print("kwargs:", kwargs)func("张三")func("李四", 20)func("王五", 22, "Python", 3.14)func("赵六", 19, "篮球", height=180, weight=75)完整的参数定义顺序可以记为:
仅限位置参数→ 普通位置或关键字参数→ *args→ 仅限关键字参数→ **kwargs默认值可以出现在允许的位置上,但必须符合 Python 的语法约束。
7. 参数的打包与解包
7.1 定义函数时:打包
• *args:把多个位置参数打包为元组。
• **kwargs:把多个关键字参数打包为字典。
def show_info(*args, **kwargs): print("位置参数:", args) print("关键字参数:", kwargs)show_info(11, 22, 33, name="lili", age=21)7.2 调用函数时:解包
• *可迭代对象:拆成多个位置参数。
• **字典:拆成多个关键字参数,字典键必须与形参名对应,并且必须是字符串。
def show_info(name, age, city): print(name, age, city)values = ("小明", 18)options = {"city": "北京"}show_info(*values, **options)等价于:
show_info("小明", 18, city="北京")打包与解包的区别取决于出现位置:
8. 函数的返回值
8.1 return 的两个作用
return 同时具有两个作用:
1. 结束当前函数;
2. 把数据返回给调用者。
def add(a, b): return a + bresult = add(10, 20)print(result)执行到 return 后,当前函数立即结束,后面的代码不会继续执行:
def test(): print("return 之前") return 100 print("这行不会执行")return 不一定写在函数的最后一行,它经常与条件判断结合,用于提前结束函数:
def check_age(age): if age < 0: return "年龄不能小于 0" if age < 18: return "未成年" return "成年"8.2 没有显式返回值
函数没有写 return,或者只写了 return,都会返回 None:
def say_hello(): print("Hello")result = say_hello()print(result) # Noneprint(type(result)) # <class 'NoneType'>注意:打印和返回是两件不同的事。
def add_and_print(a, b): print(a + b) # 只是显示结果,没有把结果返回result = add_and_print(1, 2)print(result) # None8.3 返回多个值
Python 函数可以一次返回多个值,这些值实际上会被打包成元组。
def calculate(x, y): return x + y, x - yresult = calculate(10, 3)print(result) # (13, 7)print(type(result)) # <class 'tuple'>也可以直接解包接收:
total, difference = calculate(10, 3)print(total)print(difference)