您的位置:

Python arg3:如何优雅地处理函数参数?

一、Python函数参数的基础知识

在Python中,函数参数可以分为两种,分别是位置参数和关键字参数。位置参数是指通过位置顺序传递给函数的参数,而关键字参数是通过键值对传递给函数的参数。

def func1(a, b, c):
    print(a, b, c)

func1(1, 2, 3) # 输出1 2 3

func1(c=3, b=2, a=1) # 输出1 2 3

func1(1, c=3, b=2) # 输出1 2 3

在函数定义中,位置参数必须放在最前面,而关键字参数必须放在位置参数后面。如上述代码,函数func1有三个位置参数(a、b、c),传参时可以按照参数顺序传递,也可以通过键值对传递参数。如果混合使用位置参数和关键字参数,那么位置参数必须在前面。

二、Python函数参数的默认值

在Python中,函数参数可以设置默认值,如下所示:

def func2(a, b=2, c=3):
    print(a, b, c)

func2(1) # 输出1 2 3

func2(1, 4) # 输出1 4 3

func2(1, c=5) # 输出1 2 5

func2(c=5, a=1) # 输出1 2 5

在上面的代码中,函数func2有三个参数,其中b和c有默认值。如果在调用函数时没有传递b和c的参数,那么默认值将被使用。如果传递了b和c的参数,那么将覆盖默认值。

三、Python函数参数的收集

有时候我们希望能够处理不定数量的参数,Python提供了两种传递不定数量参数的方法:收集参数和关键字收集参数。

1、使用*args来收集参数。

def func3(a, b, *args):
    print(a, b)
    print(args)

func3(1, 2, 3, 4, 5) # 输出1 2 (3, 4, 5)

func3(1, 2) # 输出1 2 ()

在上面的代码中,函数func3有三个参数,其中*args表示收集所有未匹配的位置参数。在第一次调用时,传递了5个参数,其中第一个和第二个参数被分配给a和b,而剩余的参数被收集到args列表中。在第二次调用时,只传递了两个参数,args列表为空。

2、使用**kwargs来收集关键字参数。

def func4(a, b, **kwargs):
    print(a, b)
    print(kwargs)

func4(1, 2, x=3, y=4, z=5) # 输出1 2 {'x': 3, 'y': 4, 'z': 5}

func4(1, 2) # 输出1 2 {}

在上面的代码中,函数func4有三个参数,其中**kwargs表示收集所有未匹配的关键字参数。在第一次调用时,传递了三个关键字参数,其中第一个和第二个参数被分配给a和b,而剩余的关键字参数被收集到kwargs字典中。在第二次调用时,没有传递任何关键字参数,kwargs字典为空。

四、Python函数参数的传递

在Python中,函数参数的传递可以是值传递或引用传递。但是,Python中所有的函数参数传递都是引用传递。

def func5(lst):
    lst.append(4)

lst = [1, 2, 3]
func5(lst)
print(lst) # 输出[1, 2, 3, 4]

在上面的代码中,函数func5接收一个列表参数,向该列表添加一个元素。在主程序中,创建一个列表,并将其传递给函数func5。在函数中,通过append()函数向列表中添加一个元素。在主程序中,输出列表元素,发现列表中已经添加了一个元素,说明列表是可以被函数中修改的。

五、可以被避免的函数参数的陷阱

在函数参数的处理过程中,有一些陷阱需要避免。

1、使用可变参数作为默认参数。

def func6(a, b=[]):
    b.append(a)
    print(b)

func6(1) # 输出[1]

func6(2) # 输出[1, 2],而不是[2]

在上面的代码中,函数func6接收两个参数,其中b的默认值是一个空列表。每次调用函数时,如果没有传递b的值,都会使用同一个默认值列表对象。因此,在第二次调用时,输出的列表包括了前一次调用的结果。为了避免这个陷阱,可以将默认参数设置为None,并在函数中判断参数是否为None,如果是,则创建一个空列表。

def func6_fixed(a, b=None):
    if b is None:
        b = []
    b.append(a)
    print(b)

func6_fixed(1) # 输出[1]

func6_fixed(2) # 输出[2]

2、改变可变参数的长度。

def func7(lst=[]):
    lst.append(1)
    return lst

print(func7()) # 输出[1]

print(func7()) # 输出[1, 1]

print(func7()) # 输出[1, 1, 1]

在上面的代码中,函数func7返回一个被添加了一个元素1的列表对象。由于在第一次调用时,没有传递任何参数,使用了默认参数值。在第二次和第三次调用时,由于第一次调用修改了默认参数的数值,因此输出的结果不正确。为了避免这个陷阱,可以将可变参数替换为不可变类型。

def func7_fixed(lst=None):
    if lst is None:
        lst = []
    lst.append(1)
    return lst

print(func7_fixed()) # 输出[1]

print(func7_fixed()) # 输出[1]

print(func7_fixed()) # 输出[1]

六、总结

Python函数参数可以分为位置参数和关键字参数,可以设置默认值,还可以收集不定数量的参数。在函数参数传递过程中,所有传递的参数都是引用传递,而不是值传递。在函数参数处理过程中需要注意避免一些陷阱。