您的位置:首页 > 编程语言 > Python开发

Python高级特性:函数参数传递研究

2015-03-28 22:17 489 查看

简介

本文简要介绍Python函数参数传递的基本原理

函数参数传递例子

为了更好的了解Python函数传递的特点,我们以一个简单的例子,先做一个基本的测试:
'''
Created on 2015年3月28日

@author: bob
'''

def changer(num, lst):
    num = 1
    lst[0] = "Shanghai"
    print("num=", num)
    print("lst=", lst)

if __name__ == '__main__':
    number = 20
    addrs = ["Beijing", "China"]
    changer(number, addrs)
    print("====================")
    print("number=", number)
    print("addrs=", addrs)   
函数changer有两个参数,其中number输入为int型不可变对象,lst为列表对象。在函数中对两个输入参数进行了修改。我们接下来看一下函数的运行结果:
num= 1
lst= ['Shanghai', 'China']
====================
number= 20
addrs= ['Shanghai', 'China']

函数传递参数原理分析

从运行结果上看,number变量在函数调用后,其值并没有改变;而addr列表变量却发生了变化。参考下图,我们来研究一下在函数运行前和函数退出前,变量和状态引用关系的变化情况:



在Python中,参数是通过赋值进行传递的,函数中的参数名可以在调用时通过变量实现共享对象。从上图中的左图可以看出,number变量和函数参数num共同引用了相同的对象20;addrs变量和函数参数lst则功能引用了相同的对象列表["Beijing", "China"]。函数changer均对传入参数进行了修改,但对变量number和addrs的影响不同,在于Python对不可变对象和可变对象的处理方式不同:

对于不可变对象,如int类型,元组和字符串等,参数名称可能最初共享传递的对象(实质上是指向这些对象的指针),但只是临时的,仅当函数第一次调用的时候如此。只要对参数名重新赋值,这种关系就结束了。因为不可变对象不支持在原处修改。我们可以看出,在函数调用结束时,number变量和num函数参数引用了不同的对象。
对于可变对象,当参数传递项列表和字典这样的可修改对象的时候,就需要注意,对这样的对象的原处修改,可能在函数退出后依然有效,并由此影响到调用者。

参数传递总结

Python通过赋值进行传递的机制与C语言的参数传递机制非常相似:

不可变参数通过“值”进行传递。像元组、字符串这样的对象是通过对象引用而不是拷贝进行传递的,但是你不可能在原处修改来改变不可变对象,实际效果像是创建了一份拷贝。
可变对象通过"指针"进行传递:像列表和字典这样的对象也是通过对象引用进行传递的,但是由于你可以在原处修改可变对象,类似于C语言使用指针进行传递的情况。

本质上,Python的参数传递都是通过引用来进行传递的,由于不可变对象和可变对象的修改机制不同,造成了不同的结果。这本身不是bug,而是Python的工作方式。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: