函数参数
# 函数参数
在 Python 中,函数的参数定义灵活度非常大,分为位置参数、默认参数、动态参数和关键字参数,这些都是形参的种类。
# 位置参数
也叫必传参数,顺序参数,是最重要的,也是必须在调用函数时明确提供的参数。位置参数必须按先后顺序,一一对应,个数不多不少的传递。
代码示例:
def add(a, b, c):
return a + b + c
result = add(1, 2, 3)
2
3
4
注意: Python 在做函数参数传递的时候不会对数据类型进行检查,理论上你传什么类型都可以,但上面的 add 函数,如果你传递了一个字符串和两个数字,结果是弹出异常,因为字符串无法和数字相加。这就是 Python 的弱数据类型和动态语言的特点。在简单、方便的时候,需要你自己去实现数据类型检查。
# 默认参数
在函数定义时,如果给某个参数提供一个默认值,这个参数就变成了默认参数,不再是位置参数了。在调用函数的时候,我们可以给默认参数传递一个自定义的值,也可以使用默认值。
代码示例:
def power(x, n = 2):
return x**n
ret1 = power(10) # 使用默认的参数值 n = 2
ret2 = power(10, 4) # 将 4 传给 n,实际计算 10**4 的值
2
3
4
5
在设置默认参数时,有几点要注意:
默认参数必须在位置参数后面。
当有多个默认参数的时候,通常将更常用的放在前面,变化较少的放后面。
在调用函数的时候,尽量给实际参数提供默认参数名。
- 一切没有提供参数名的实际参数,都会当做位置参数按顺序从参数列表的左边开头往右匹配。
如果在位置参数传递时,给实参指定位置参数的参数名,那么位置参数也可以不按顺序调用。
默认参数尽量指向不变的对象
- 这个很重要,看如下代码,并分析下打印结果:
def func(a=[]): a.append("A") return a print(func()) print(func()) print(func())
1
2
3
4
5
6
7分析:Python 函数体在被读入内存的时候,默认参数
a
指向的空列表对象就会被创建,并放在内存里了。因为默认参数a
本身也是一个变量,保存了指向对象[]
的地址。每次调用该函数,往a
指向的列表里添加一个A
。a
没有变,始终保存的是指向列表的地址,变的是列表内的数据。为了避免这个问题,需要使用不可变的数据类型作为默认值:
def func(a=None): # 注意下面的if语句 if a is None: a = [] a.append("A") return a print(func()) print(func()) print(func())
1
2
3
4
5
6
7
8
9
10将默认参数
a
设置为一个类似None
、数字或字符串之类的不可变对象。在函数内部,将它转换为可变的类型,比如空列表。这样一来,不管调用多少次,运行结果都是['A']
了。
# 动态参数
顾名思义,动态参数就是传入的参数的个数是动态的,可以是 1 个、2 个到任意个,还可以是 0 个。
Python 的动态参数有两种,分别是 *args
和 **kwargs
,这里面的关键是一个和两个星号的区别,而不是 args 和 kwargs 在名字上的区别,实际上可以使用任何名字,但这似乎是大家默认的规范。
注意:动态参数,必须放在所有的位置参数和默认参数后面。
def func(name, age, sex='male', *args, **kwargs):
pass
2
# *args
一个星号表示接收任意个参数。调用时,会将实际参数打包成一个元组传入形式参数。如果参数是个列表,会将整个列表当做一个参数传入。例如:
def func(*args):
for arg in args:
print(arg)
func('a', 'b', 'c')
func([1, 2, 3])
2
3
4
5
6
# **kwargs
两个星表示接受键值对的动态参数,数量任意。调用的时候会将实际参数打包成字典。例如:
def func(**kwargs):
print(kwargs)
for kwg in kwargs:
print(kwg, kwargs[kwg])
func(k1='v1', k2=[0, 1, 2])
2
3
4
5
6
# 万能参数
当 *args
和 **kwargs
组合起来使用,理论上能接受任何形式和任意数量的参数,在很多代码中我们都能见到这种定义方式。需要注意的是,*args
必须出现在 **kwargs
之前。
# 关键字参数
关键字参数需要一个特殊分隔符 *
(独占一个参数位),*
后面的参数被视为关键字参数。
在函数调用时,关键字参数必须传入参数名,否则调用将报错。同时,关键字参数没有默认值时必须传递,有默认值时可以不传递。
代码示例:
# 没有默认值时必须传递关键字参数
def student(name, age, *, sex):
pass
student(name="jack", age=18, sex='male')
# 有默认值时可以不传递关键字参数
def student(name, age, *, sex='male'):
pass
student(name="jack", age=18)
2
3
4
5
6
7
8
9
10
11
Python 的函数参数种类多样、形态多变,既可以实现简单的调用,又可以传入非常复杂的参数。需要我们多下功夫,多写实际代码,多做测试,逐步理清并熟练地使用参数。
(完)