美文网首页我的Python之旅
对Python函数传参的一些思考

对Python函数传参的一些思考

作者: resolvewang | 来源:发表于2018-06-22 10:33 被阅读28次

今天看到这样一个问题: Python 的函数是怎么传递参数的,有了一些兴趣,因为以前都是直接信的一个流传度较广的说法

对于不可变对象作为函数参数,相当于C系语言的值传递;
对于可变对象作为函数参数,相当于C系语言的引用传递。

那么事实上真是如此吗?我们来看几个例子。

首先我们来看看第一个说法,这里我实验环境是Python3.6。

对于不可变对象作为函数参数进行传递,这里我分别以inttuple进行测试

def test_immutable_for_simpledata(args):
    print('============')
    print(2, id(args))
    args = args + 10
    print(3, args)
    print(4, id(args))
    print('============')


if __name__ == '__main__':
    cur = 5000
    print(1, id(cur))
    test_immutable_for_simpledata(cur)
    print(5, cur)
    print(6, id(cur))

结果如下

1 42301856
============
2 42301856
3 5010
4 42301616
============
5 5000
6 42301856

我们看第一步和第二步,两者打印出来的地址是一样的,这可以证明Python对不可变类型传参是使用的引用传参,但是为什么函数中用了args+10,函数外面的args值还是没变呢?我们可以看到第四步的args的地址其实已经变了。即说明加10和未加10两个时间点是两个不同的对象。为什么是这样呢?这就需要理解什么是不可变对象了。在我理解来,不可变对象就是它的成员元素不变,比如对于简单对象(如int,float)来说,就是它的值不变,对于复合类型(如tuple)来说,就是它的成员元素(即地址)不变。回到代码中,这里是基本类型的不可变对象,对它进行运算操作其实就是创建新的对象,然后将原先的变量名绑定到新的对象上。读者前一句话没读懂的话,可以去了解一下Python的名字空间。

为了加深读者的理解,我们再以tuple为例进行测试。代码如下

def test_immutable_for_tuple(args):
    print('============')
    print(2, id(args))
    args[0].append(5)
    print(3, args)
    print(4, id(args))
    print('============')
if __name__ == '__main__':
    cur = ([0], 1)
    print(1, id(cur))
    test_immutable_for_tuple(cur)
    print(5, cur)
    print(6, id(cur))

结果如下

1 33951020
============
2 33951020
3 ([0, 5], 1)
4 33951020
============
5 ([0, 5], 1)
6 33951020

这次的结果和上次明显不同了。虽然tuple是不可变对象,我们使用tuple为参数传入函数中,然后对tuple中的列表元素进行了操作,结果函数外部的变量也发生了变化。我们也可以看到参数的地址在函数内外其实都一样。

根据上述测试,我们可以得出一个结论,对于不可变对象的函数传参,依然是传的引用(地址)。对于简单类型,在函数内对其操作之所以不会影响函数范围外的值,是因为运算中的赋值操作产生了新的对象,而不是对原有对象的改变。而对于一些复杂类型,就可以比较清晰的看出,函数内参数的改变同样会影响函数外的变量。

对于可变对象,我们同样可以使用上述逻辑去验证,由于篇幅,我就不啰嗦了。

最终可以得到的结论是,Python中的函数通过引用传参。

相关文章

  • 对Python函数传参的一些思考

    今天看到这样一个问题: Python 的函数是怎么传递参数的,有了一些兴趣,因为以前都是直接信的一个流传度较广的说...

  • 19-3-18 python函数传参方式

    python函数传参跟js很像: 直接传参方式: 形参实参按顺序一一对应,跟js一样 指定传参 参数顺序不用一一对...

  • python函数

    python函数 什么是函数 函数语法 调用函数 函数参数形参与实参传参指定参数传参参数默认值可变参数参数解包参数...

  • Python的函数返回值返回的是值还是引用?

    关于Python函数传参是传值还是传引用?这一问题网上都有很多的讨论,这篇博客解释比较清楚,结论是:Python参...

  • Python共享传参

    函数的参数作为引用 Python 唯一支持的参数传递是 共享传参 ,也就是常说的引用传参。函数内部的形参是实参的别...

  • 研究Python中函数的传参方式

    注:原创研究目的:研究Python中函数的传参方式:传值、传地址研究对象:Python的list和Numpy的ar...

  • python函数传参

    * 和** test(*args)* 的作用其实就是把序列args中的每个元素,当作位置参数传进去。*所对应的形参...

  • Python函数传参

    函数代码块以def关键字开头,后接函数标识符名称和圆括号() 所有传入的参数和自变量都必须放在圆括号内,可以在圆括...

  • inspect.Parameter.KEKWORD_ONLY 引

    在看廖雪峰老师的python实战时,用到了inspect函数,突然发现对函数传参类型比较陌生,在此记录一下。 in...

  • Python脚本传参(argparse模块)2022-08-23

    Python传参 简便版 进阶版 Python使用argparse模块传参 Python系统自带的传参用到sys模...

网友评论

    本文标题:对Python函数传参的一些思考

    本文链接:https://www.haomeiwen.com/subject/majcyftx.html