Python函数中参数是值传递,还是引用传递?

栏目: Python · 发布时间: 7年前

内容简介:学过Java、C系列、PHP等语言的小伙伴对值传递和引用传递一定不陌生,那么在Python中如何进行引用传递呢?要回答这个问题,我们首先来看一下在Python函数中参数是值传递,还是引用传递?不妨先来看两段代码看完这个,可能小伙伴会说,Python中函数的参数是值传递,别忙下结论,再来看一下这段代码

学过 Java 、C系列、 PHP 等语言的小伙伴对值传递和引用传递一定不陌生,那么在 Python 中如何进行引用传递呢?要回答这个问题,我们首先来看一下在Python函数中参数是值传递,还是引用传递?

不妨先来看两段代码

def foo(arg):
    arg = 2
    print(arg)

a = 1
foo(a)  # 输出:2
print(a) # 输出:1

看完这个,可能小伙伴会说,Python中函数的参数是值传递,别忙下结论,再来看一下这段代码

def bar(args):
    args.append(1)

b = []
print(b)# 输出:[]
print(id(b)) # 输出:4324106952
bar(b)
print(b) # 输出:[1]
print(id(b))  # 输出:4324106952

看了这段代码,又好像是引用传递。这时候,就把你搞晕了,不禁会问:到底是啥?

不急,让我们先了解一下Python中变量与对象的关系

Python 中一切皆为对象,数字是对象,列表是对象,函数也是对象,任何东西都是对象。而变量是对象的一个引用(又称为名字或者标签),对象的操作都是通过引用来完成的。例如,[]是一个空列表对象,变量 a 是该对象的一个引用,在 Python 中,「变量」更准确叫法是「名字」,赋值操作 = 就是把一个名字绑定到一个对象上。就像给对象添加一个标签。

a = 1

这相当于给数字1挂了一个标签a

a = 2

这相当于给数字2挂了一个标签a,而这个a是从1身上撕下来的

Python函数中参数是值传递,还是引用传递?

b = a

这相当于给数字2挂了两个标签:a和b,通过这两个标签都可以对对象2操作

Python函数中参数是值传递,还是引用传递?

变量本身没有类型信息,类型信息存储在对象中,这和C/C++中的变量有非常大的出入(C中的变量是一段内存区域)

Python 函数中,参数的传递本质上是一种赋值操作,而赋值操作是一种名字到对象的绑定过程。

明白了这些,我们再回头看第一段代码:

Python函数中参数是值传递,还是引用传递?

在代码段1中,变量 a 绑定了 1,调用函数 foo(a) 时,相当于给参数 arg 赋值 arg=1,这时两个变量都绑定了 1。在函数里面 arg 重新赋值为 2 之后,相当于把 1 上的 arg 标签撕掉,贴到 2 身上,而 1 上的另外一个标签 a 一直存在。因此 print(a) 还是 1。

而第二段代码:

Python函数中参数是值传递,还是引用传递?

执行 append 方法前 b 和 arg 都指向(绑定)同一个对象,执行 append 方法时,并没有重新赋值操作,也就没有新的绑定过程,append 方法只是对列表对象插入一个元素,对象还是那个对象,只是对象里面的内容变了。因为 b 和 arg 都是绑定在同一个对象上,执行 b.append 或者 arg.append 方法本质上都是对同一个对象进行操作,因此 b 的内容在调用函数后发生了变化(但id没有变,还是原来那个对象)

最后,回到问题本身,究竟是是传值还是传引用呢?说传值或者传引用都不准确。非要安一个确切的叫法的话,叫传对象(call by object)。如果作为面试官,非要考察候选人对 Python 函数参数传递掌握与否,与其讨论字面上的意思,还不如来点实际代码。

来看一个初学者会犯的错误:

def bad_append(new_item, a_list=[]):
    a_list.append(new_item)
    return a_list

用可变(mutable)对象作为参数的默认值。函数定义好之后,默认参数 a_list 就会指向(绑定)到一个空列表对象,每次调用函数时,都是对同一个对象进行 append 操作。因此这样写就会有潜在的bug,同样的调用方式返回了不一样的结果。

>>> print bad_append('one')
['one']
>>> print bad_append('one')
['one', 'one']

Python函数中参数是值传递,还是引用传递?

而正确的姿势是将参数默认值初始化为None

def good_append(new_item, a_list=None):
    if a_list is None:
        a_list = []
    a_list.append(new_item)
    return a_list

Python函数中参数是值传递,还是引用传递?


以上所述就是小编给大家介绍的《Python函数中参数是值传递,还是引用传递?》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Responsive Web Design

Responsive Web Design

Ethan Marcotte / Happy Cog / 2011-6 / USD 18.00

From mobile browsers to netbooks and tablets, users are visiting your sites from an increasing array of devices and browsers. Are your designs ready? Learn how to think beyond the desktop and craft be......一起来看看 《Responsive Web Design》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码