Bullet:Python的函数中参数是引用吗?

别的语言中关于函数有传值和传引用的区分。
关于此,流传很广的一个说法是
他们在现象的区别之一就是值传递后的变化,受到影响的就是引用,未受到影响的就是传值。
 
在学习中,也曾碰到过这个问题,网上关于这个也是有着一些争论,各执一词。
但是官方文档中,却明确写着是call by object reference。
 
The actual parameters (arguments) to a function call are introduced in the local symbol table of the called function when it is called; thus, arguments are passed using call by value (where the value is always an object reference, not the value of the object). [1] When a function calls another function, a new local symbol table is created for that call.
 

Actually, call by object reference would be a better description, since if a mutable object is passed, the caller will see any changes the callee makes to it (items inserted into a list).
 
call by object reference,那么以下代码段会让人产生疑问
[root@ansible01 python]# cat func.py
def func(a):
a = 2
return a
 
b = 1
 
func(b)
 
print b
[root@ansible01 python]# python func.py
1
[root@ansible01 python]#
 
其中b的值并未发生变化。

 

要解释这个问题,可以接住python提供的一个函数id。
[root@ansible01 python]# pydoc id
Help on built-in function id in module __builtin__:
 
id(...)
id(object) -> integer
 
Return the identity of an object. This is guaranteed to be unique among
simultaneously existing objects. (Hint: it's the object's memory address.)
 

 

将程序改写如下
[root@ansible01 python]# cat func.py
def func(a):
print "argu a id = %d , before assignment." % id(a)
a = 2
print "argu a id = %d , after assignment." % id(a)
return a
 
b = 1
print "Variable b id = %d , before calling function func." % id(b)
 
func(b)
print "Variable b id = %d , after calling function func." % id(b)
[root@ansible01 python]# python func.py
Variable b id = 14570296 , before calling function func.
argu a id = 14570296 , before assignment.
argu a id = 14570272 , after assignment.
Variable b id = 14570296 , after calling function func.
[root@ansible01 python]#

 

 
可以见到,变量b在函数调用前后的ID没有发生变化,值也未发生变化。在函数体内,在第一次赋值之前ID也未发生变化,但在赋值之后发生了变化。
正如官方文档描述的那样。
The execution of a function introduces a new symbol table used for the local variables of the function. More precisely, all variable assignments in a function store the value in the local symbol table; whereas variable references first look in the local symbol table, then in the local symbol tables of enclosing functions, then in the global symbol table, and finally in the table of built-in names. Thus, global variables cannot be directly assigned a value within a function (unless named in a global statement), although they may be referenced.
 
其实符合流传最广的那个说法是python中的复合类型,比如以下代码段
[root@ansible01 python]# cat func_1.py
a=[1]
 
def func(b):
b[0] = 2
 
func(a)
 
print a[0]
[root@ansible01 python]# python func_1.py
2

 

 
就如文档的脚注所言,如果传递的是可变的对象调用者可见到被调用者中间的变化。
 
所以,python中的函数传递就如官方文档所言,可叫做call by object reference,为何有不合流传较广的说法的现象出现,概由函数体内本地符号表的缘故,是一个新的引用。
 
而为啥会有区别,则要考虑python中有

可更改(mutable)与不可更改(immutable)对象

posted @ 2015-11-27 00:55  syksky  阅读(486)  评论(0编辑  收藏  举报