Python语言参数传递,既不是传值也不是传引用
小标 2018-11-06 来源 : 阅读 864 评论 0

摘要:本文主要向大家介绍了Python语言参数传递,既不是传值也不是传引用,通过具体的内容向大家展示,希望对大家学习Python语言有所帮助。

本文主要向大家介绍了Python语言参数传递,既不是传值也不是传引用,通过具体的内容向大家展示,希望对大家学习Python语言有所帮助。

面试的时候,有没有被问到Python传参是传引用还是传值这种问题?有没有听到过Python传参既不是传值也不是传引用这种说法?一个小小的参数默认值也可能让代码出现难以查找的bug?
如果你也遇到过上面的问题,不妨我们来探究下Python函数传递的种种。
  万物皆对象
Python中有一个非常重要的概念——万物皆对象,无论是一个数字、字符串,还是数组、字典,在Python中都会以一个对象的形式存在。
a = 123
对于上面这行代码,在Python看来就是创建一个PyObject对象,值为123,然后定义一个指针a,a指向这个PyObject对象。
  可变对象和不可变对象
Python中的对象分为两种类型,可变对象和不可变对象,不可变对象指tuple、str、int等类型的对象,可变对象指的是dict、list、自定义对象等类型的对象,我们用一段代码说明他们的区别。
a = [1, 2, 3]
print(id(a))  # 2587116690248
a += [4]
print(id(a)) # 2587116690248

b = 1
print(id(b)) # 2006430784
b += 1
print(id(b)) # 2006430816
上面代码中我们分别定义了一个可变对象和一个不可变对象,并且对他们进行修改,打印修改前后的对象标识可以发现,对可变对象进行修改,变量对其引用不会发生变化,对不可变对象进行修改,变量引用发生了变化。

上图是一个可变对象,当修改对象时,例如删除数组中的一个元素,实际上把其中一个元素从对象中移除,对象本身的标识是不发生变化的。

改变一个不可变对象时,例如给一个int型加2,语法上看上去是直接修改了i这个对象,但是如前面所说,i只是一个指向对象73的一个变量,Python会将这个变量指向的对象加2后,生成一个新的对象,然后再让i指向这个新的对象。
  参数传递时的表现
了解了对象的原理后,我们就可以来尝试理解一下参数传递时他们的不同表现了。
a = [1, 2, 3]
print(id(a))  # 1437494204232
def mutable(a):
    print(id(a))  # 1437494204232
    a += [4]
    print(id(a))  # 1437494204232
mutable(a)

b = 1
print(id(b))  # 2006430784
def immutable(b):
    print(id(b))  # 2006430784
    b += 1
    print(id(b))  # 2006430816
immutable(b)
通过上面的代码可以看出,修改传进的可变参数时,会对外部对象产生影响,修改不可变参数时则不会影响。
概括地说,Python参数传递时,既不是传对象也不是传引用,之所以会有上述的区别,跟Python的对象机制有关,参数传递只是给对象绑定了一个新的变量(实际上是传递C中的指针)。
  参数传递时的坑
理解了参数传递的逻辑,我们需要注意一下这种逻辑可能引发的问题。
def test(b=[]):
    b += [1]
    print(b)

test()  # [1]
test()  # [1, 1]
test()  # [1, 1, 1]
上面的代码的输出,按照可变对象传参的逻辑,应该每次调用都输出1才对,而实际输出看上去好像默认参数好像只生效了一次。原因在于Python的函数也是对象(万物皆对象),这个对象只初始化一次,加上参数又是不可变对象,所以每次调用实际上都修改的是一个对象。
解决这个问题,推荐再参数传递可变对象时,默认值设置为None,在函数内部对None进行判断后再赋予默认值。
def test(b=None):
    b = b or []
    b += [1]
    print(b)

test()  # [1]
test()  # [1]
test()  # [1]
再看一段代码。
i = 1
def test(a=i):
    print(a)

i = 2
test()  # 1
由于参数默认值是在函数定义时而不是函数执行时确定的,所以这段代码test方法的参数默认值时1而不是2。    

本文由职坐标整理并发布,希望对同学们学习Python有所帮助,更多内容请关注职坐标编程语言Python频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程