欢迎来到赛兔子家园

Python函数参数传递机制

根据实际参数的类型不同,函数参数的传递方式分为值传递和引用传递(又称为地址传递),Python 底层是如何实现它们的呢?Python 中函数参数由实参传递给形参的过程,是由参数传递机制来控制的。

Python函数参数的值传递机制

Python 函数参数的值传递,其本质就是将实际参数值复制一份,将其副本传给形参。这意味着,采用值传递方式的函数中,无论其内部对参数值进行如何修改,都不会影响函数外部的实参。

下面程序演示了函数参数进行值传递的效果:

def demo(a,b):
    '''a、b变量的值互换'''
    a,b = b,a
    print("demo函数里面,a={0},b={1}".format(a,b))

a = 6
b = 9
demo(a,b)
print("函数外部,a={0},b={1}".format(a,b))

运行结果:

demo函数里面,a=9,b=6
函数外部,a=6,b=9

从上面的运行结果来看,在demo() 函数里,经过交换形参 a 和  b 的值,它们的值分别变成了 9 和 6,但函数外部变量 a 和 b 的值依然是 6 和 9。这也证实了,demo() 函数的参数传递机制,采用的是值传递,函数内部使用的形参 a 和 b,和实参 a、b 没有任何关系。

demo() 函数中形参 a 和 b,各自分别是实参 a、b 的复制品。

Python函数参数引用传递

如果实际参数的数据类型是可变对象(列表、字典),则函数参数的传递方式将采用引用传递方式。

下面程序示范了引用传递参数的效果:

def demo(dw):
    '''实现dw的a和b两个元素值互换'''
    dw["a"],dw["b"] =dw["b"],dw["a"]
    print("demo函数里面dw",dw)

dw = {"a": 6, "b": 9}
demo(dw)
print("函数外面dw", dw)

 运行结果:

demo函数里面dw {'a': 9, 'b': 6}
函数外面dw{'a': 9 'b': 6}

从上面的运行结果来看,在demo() 函数里,dic 字典的 name、age 两个元素的值被交换成功。不仅如此,当demo() 函数执行结束后,主程序中 dw 字典的 name、age 两个元素的值也被交换了。
注意,这里这很容易造成一种错觉,读者可能认为,在此demo() 函数中,使用 dic 字典,就是外界的 dic 字典本身,而不是他的复制品。这只是一种错觉,实际上,引用传递的底层实现,依旧使用的是值传递的方式。下面还是结合示意图来说明程序的执行过程。
程序开始创建了一个字典对象,并定义了一个 dic 引用变量(其实就是一个指针)指向字典对象,这意味着此时内存中有两个东西:对象本身和指向该对象的引用变量。此时在系统内存中的存储示意图如图 所示:

                   

接下来主程序开始调用demo() 函数,在调用demo() 函数时,dw 变量作为参数传入demo() 函数,这里依然采用值传递方式:把主程序中 dw 变量的值赋给demo() 函数的 dw 形参,从而完成demo() 函数的 dw 参数的初始化。值得指出的是,主程序中的 dw 是一个引用变量(也就是一个指针),它保存了字典对象的地址值,当把 dw 的值赋给demo() 函数的 dw 参数后,就是让demo() 函数的 dw 参数也保存这个地址值,即也会引用到同一个字典对象。图 5 显示了 dw 字典传入demo() 函数后的存储示意图。

 

 

 这种参数传递方式是不折不扣的值传递方式,系统一样复制了dw 的副本传入demo() 函数。但由于 dw 只是一个引用变量,因此系统复制的是 dw 变量,并未复制字典本身。
当程序在demo() 函数中操作 dw 参数时,由于 dw 只是一个引用变量,故实际操作的还是字典对象。此时,不管是操作主程序中的 dw 变量,还是操作demo() 函数里的 dw 参数,其实操作的都是它们共同引用的字典对象,它们引用的是同一个字典对象。因此,当在demo() 函数中交换 dw 参数所引用字典对象的 a、b 两个元素的值后,可以看到在主程序中 dw 变量所引用字典对象的 a、b 两个元素的值也被交换了。

为了更好地证明主程序中的 dw 和demo() 函数中的 dw 是两个变量,在demo() 函数的最后一行增加如下代码:

def demo(dic):
    ...
    dic = None

把demo() 函数中的 dw 赋值为 None 后,在demo() 函数中失去了对字典对象的引用,不可再访问该字典对象。但主程序中的 dw 变量不受任何影响,依然可以引用该字典对象,所以依然可以输出字典对象的 a、b 元素的值。
通过上面介绍可以得出如下两个结论:

  1. 不管什么类型的参数,在 Python 函数中对参数直接使用“=”符号赋值是没用的,直接使用“=”符号赋值并不能改变参数。
  2. 如果需要让函数修改某些数据,则可以通过把这些数据包装成列表、字典等可变对象,然后把列表、字典等可变对象作为参数传入函数,在函数中通过列表、字典的方法修改它们,这样才能改变这些数据。

posted on 2024-03-07 10:10  赛兔子  阅读(21)  评论(0编辑  收藏  举报

导航