形参在传递的过程中会改变
在Python中,函数是一段代码,它由参数(也可以称为形式参数)定义,可以被独立调用,并且通常返回一个值。当我们传递参数给函数时,这些参数被称为实际参数。在Python中,函数的参数可分为两类:可变参数和不可变参数。不可变参数是指在程序执行过程中不能被改变的参数。换句话说,就是无法让参数指向新的对象。而可变参数是指可以被修改的参数。
不可变参数
在Python中,不可变参数包括:int
、float
、str
、tuple
、frozenset
等类型的数据。在函数中如果对这些参数进行修改,那么会生成一个新的对象,而不是修改原来的参数。下面我们来看一个例子:
def test_func(num):
num += 1
return num
n = 1
print("调用函数前,n=",n)
test_func(n)
print("调用函数后,n=",n)
在上面的例子中,我们定义了一个函数test_func
,函数中的参数num
是一个不可变参数。我们将变量n
赋值为1,然后调用test_func(n)
,并输出调用前后n
的值。运行结果如下:
调用函数前,n= 1
调用函数后,n= 1
从结果中我们可以看出,虽然函数test_func
对参数num
进行了加1的操作,但是调用函数前后n
的值并没有改变。这是因为参数num
只是n
的一个副本,对参数进行的修改不会影响到原来的变量。
可变参数
在Python中,可变参数包括:list
、dict
、set
等类型的数据。在函数中,如果对这些参数进行修改,实际上在函数之外的对象也会发生改变。下面我们来看一个例子:
def test_func(li):
li.append(4)
return li
lst = [1,2,3]
print("调用函数前,lst=",lst)
test_func(lst)
print("调用函数后,lst=",lst)
在上面的例子中,我们定义了一个函数test_func
,函数中的参数li
是一个可变参数。我们将lst
定义为一个列表,并赋值为[1,2,3]
,将其传入函数test_func
中,并输出调用前后的值。运行结果如下:
调用函数前,lst= [1, 2, 3]
调用函数后,lst= [1, 2, 3, 4]
从结果中可以看出,当我们调用函数test_func
并在其中修改可变参数li
时,lst
列表跟着改变了。这是因为当我们将lst
传入函数中时,实际上参数li
指向了lst
的内存地址,所以对参数进行的修改也会体现在外部的变量上。
如何避免不必要的副作用
在实际开发中,为了避免在函数中对变量进行修改而带来的不必要的影响,可以有以下几种方法:
使用不可变对象作为参数 可以将参数定义为如int
、float
、str
等不可变对象类型。这样就可以避免在函数中对参数进行修改。
使用可变对象的副本作为参数 可以在函数内部对可变对象的副本进行修改,从而避免对外部的对象产生影响。可以通过切片(list[:]、dict.copy()
等)的方式来实现这一点。
使用全局变量 如果变量在整个程序中都需要使用,可以将其定义为全局变量,并在函数中使用global
关键字进行引用。
总结
本文介绍了Python中的两种函数参数类型:不可变参数和可变参数。不可变参数在函数中无法被修改,而可变参数在函数中可以被修改,并会影响到函数之外的对象。在函数中避免对外部变量产生影响的方法包括使用不可变对象作为参数、使用可变对象的副本作为参数以及使用全局变量。