Python的参数传递机制

首先看以下示例:

1
2
3
4
5
6
7
8
>>> a = 1
>>> b = 1
>>> a is b
True
>>> a = [1, 2]
>>> b = [1, 2]
>>> a is b
False
  • 变量的赋值,表示让变量指向某个对象,并不是拷贝对象给变量;而一个对象是可以由多个对象指向
  • 可变对象(列表,字典,集合等)的改变,会影响所有指向该对象的变量
  • 对于不可变对象(字符串,整型,元祖)的改变,所有指向该对象的变量的值总是一样的,也不会改变。但是通过某些操作(+,=等等)更新不可变对象时,会返回一个新的对象
  • 变量可以被删除,但对象无法被删除。这也和python的垃圾回收机制相符合,只有当该对象的指向变量为0个时,才会回收该对象。

通过以下示例:

1
2
3
4
5
6
7
>>> a = 1
>>> b = a
>>> a += 1
>>> a
2
>>> b
1

由于1是不可变对象,a, b都是指向1这个变量,a的值变化时,相当于a的指向又会重新改变,而b的指向是没有变化的

1565256260196

而对于可变对象来说,a, b会同时指向一个内存地址,改变可变对象的值,会改变所有指向该对象的变量

1
2
3
4
5
6
7
>>> a = [1, 2]
>>> b = a
>>> a.append(3)
>>> a
[1, 2, 3]
>>> b
[1, 2, 3]

1565312225472

1
2
3
4
5
6
7
>>> def func(a):
... a = 2
...
>>> b = 1
>>> func(b)
>>> b
1

在上述例子中,变量a和b同时指向1这个对象,当执行到a = 2时,是将a重新指向了2这个对象,而b仍然还是指向的1这个对象

如果想要改变上述过程

1
2
3
4
5
6
7
>>> def func(a):
... a = 2
... return a
>>> b = 1
>>> b = func(b)
>>> b
2

可将b变量重新指向2这个对象,这样就能改变b的值

而对于可变参数来说,改变对象的值,会改变所有指向它的值

1
2
3
4
5
6
>>> def func(a):
... a.append(4)
>>> b = [1, 2, 3]
>>> func(b)
>>> b
[1, 2, 3, 4]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> def func(a):
... a += [4]
...
>>> b = [1, 2, 3]
>>> func(b)
>>> b
[1, 2, 3, 4]
>>> def func(a):
... a = a + [4]
...
>>> b = [1, 2, 3]
>>> func(b)
>>> b
[1, 2, 3]

需要注意的是,a += [4]和a = a + [4]是不相同的操作,a = a + [4]是表示新创建一个新的列表,然后让a重新指向它,而a += [4]是一个自增的过程

1
2
3
4
5
6
7
8
9
>>> a = [1]
>>> id(a)
2610677016776
>>> a += [2]
>>> id(a)
2610677016776
>>> a = a + [3]
>>> id(a)
2610680008648

总结来说:

  • 如果对象是可变的,对象改变时,指向这个对象的所有变量都会改变
  • 如果对象是不可变的,对象改变时,指向这个对象的变量不会受到影响
  • 为了安全,函数末尾尽量使用return返回
-------------本文结束感谢您的阅读-------------