微信公众号:CurryCoder的程序人生
怕什么真理无穷,进一寸有一寸的欢喜
#include
using namespace std;
/* 值传递举例 */
// 交换两个变量的值
void swap(int x, int y){
int tmp;
tmp = x;
x = y;
y = tmp;
return;
}
int main(){
int a = 1, b = 100;
cout <"交换前, a = " <",b = " swap(a, b);
cout <"交换前, a = " <",b = " return 0;
}
#include
using namespace std;
/* 引用传递举例 */
// 交换两个变量的值
void swap(int& x, int& y){
int tmp;
tmp = x;
x = y;
y = tmp;
return;
}
int main(){
int a = 1, b = 100;
cout <"交换前, a = " <",b = " swap(a, b);
cout <"交换后, a = " <",b = " return 0;
}
a = 1
b = a
a = a + 1
上面的代码虽然简单,里面却包含了python语言的一些基本原理。首先,将1赋值给a,换言之就是a指向了1这个整型对象。如下图所示:
l1 = [1, 2, 3]
l2 = l1
l1.append(4)
print("l1:", l1)
print("l2:", l2)
l1 = [1, 2, 3]
del l1
del l1删除了l1这个变量,从此之后你无法访问l1了。但是,列表对象[1,2,3]仍然存在。python程序运行时,其自带的垃圾回收机制会跟踪每个对象的引用。如果[1,2,3]这个列表对象除l1外,还在别的地方被引用。那么,[1,2,3]就不会被回收。反之,则会被回收。 对以上内容进行总结,有如下结论:
(1).变量的赋值,只是表示让变量指向了某个对象,并不表示拷贝对象的值给变量。此外,一个对象,可以被多个变量同时所指向。
(2).可变对象(如:列表、字典、集合等)的改变,会影响所有指向该对象的变量。
(3).对不可变对象(如:字符串、元组、整型等)来说,所有指向这些对象的变量的值总是一样的,不会发生改变。但是,可以通过某些操作(如:+=等)更新不可变对象的值时,会返回一个新的对象。
(4).变量可以被删除,但对象无法被删除。
上面的这段话,翻译过来就是说Python中的参数传递是赋值传递或者称为对象的引用传递。 由于Python中所有的数据类型实质都是对象,因此在参数传递时,只是让新变量与原变量指向相同的对象而已,并不存在值传递或引用传递这个说法。 下面以一个简单的例子来分析一下:Remember that arguments are passed by assignment in Python. Since assignment just creates references to objects, there’s no alias between an argument name in the caller and callee, and so no call-by-reference per se.
def foo(b):
b = 2
a = 1
foo(a)
print("a =", a) # a = 1
在上面的代码段中,函数foo()在进行参数传递时,让变量a和b同时指向了1这个整型对象。但是,当执行到b=2时,系统又会创建一个值为2的整型对象,并让变量b指向它。然而,变量a仍然指向的是1这个整型对象。所以,最终的结果是a = 1。
有的小伙伴们可能就会问,如果我就是想改变变量a的值,那又改咋办呢?方法当然是有的,只需要让函数foo()返回新的变量并赋值给a。这样,变量a就指向了一个新的整型对象。
def foo(b):
b = 2
return b
a = 1
a = foo(a)
print("a =", a) # a = 2
此外,值得注意的是:当可变对象作为函数参数传入入函数内部时,改变可变对象的值,就会影响所有指向它的变量。如下面的例子所示:
def bar(l2):
l2.append(4)
l1 = [1, 2, 3]
bar(l1)
print("l1 =", l1) # [1, 2, 3, 4]
上面的代码段中,l1和l2两个变量同时指向值为[1,2,3]的列表对象。由于列表是可变对象,执行append()函数时,在列表对象末尾插入新元素4,变量l1和l2的值都会发生变化。但是,下面这个例子就比较特殊,看似是在列表的末尾增加一个新元素,实质却得到明显不同的结果。
def func(l2):
l2 = l2 + [4]
l1 = [1, 2, 3]
func(l1)
print("l1 =", l1) # [1, 2, 3]
为啥上面代码段输出l1的结果仍然是[1,2,3]呢?为啥不会是[1,2,3,4]呢?原因在于l2 = l2 + [4]表示创建了一个末尾插入元素4的新列表对象,并且让变量l2指向这个新的列表对象。前面的整个过程与变量l1无关,因此l1的值不会改变。同样地,如果要改变l1的值,就必须让变量l1指向函数func()返回的新列表对象。如下面的代码段所示:
def func(l2):
l2 = l2 + [4]
return l2
l1 = [1, 2, 3]
l1 = func(l1)
print("l1 =", l1) # [1, 2, 3, 4]