函数的传参

 函数参数传递机制问题在本质上是调用函数(过程)和被调用函数(过程)在调用发生时进行通信的方法问题。基本的参数传递机制有两种:值传递引用传递

  • 值传递(pass-by-value)过程中,被调函数的形式参数作为被调函数的局部变量处理,即在堆栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。
  • 引用传递(pass-by-reference)过程中,被调函数的形式参数虽然也作为局部变量在堆栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过堆栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
In [1]: from ctypes import *

In [2]: import os.path

In [3]: import sys

\# 传入不可变类型

In [4]: def test(x):

  ...:   print("test before")

  ...:   print(id(c))

  ...:   c+=2

  ...:   print("test add")

  ...:   print(id(c))

  ...:   return c

In [5]: a = 2

In [6]: id(2)

Out[6]: 11496672

In [7]: n = test(a)

test before

11496672

test add

11496736

\# 传入可变类型

In [17]: def test2(x):

   ...:   print("test before")

   ...:   print(id(x))

   ...:   x[0] = 45

   ...:   print("test after")

   ...:   print(id(x))

   ...:   return x

   ...:

In [18]: e = [0,1,2,3]

In [19]: id(e)

Out[19]: 140323019352896

In [20]: g = test2(e)

test before

140323019352896

test after

140323019352896

结论:python不允许程序员选择采用传值还是传引用。Python参数传递采用的肯定是“传对象引用”的方式。这种方式相当于传值和传引用的一种综合

  • 如果函数收到的是一个可变对象(比如字典或者列表)的引用,就能修改对象的原始值--相当于通过“传引用”来传递对象。
  • 如果函数收到的是一个不可变对象(比如数字、字符或者元组)的引用,就不能直接修改原始对象--相当于通过“传值’来传递对象。

函数的返回值

与函数传参一样,返回的也是“对象引用”,如果返回的对象是可变对象,则将函数的返回值赋值给新变量之后,对新变量的修改会直接影响到源对象。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# 传入可变类型

In [4]: dic = {"luenci":'a'}

In [9]: def return_test(x):

  ...:   print(id(x))

  ...:   return x

  ...:

In [10]: new = return_test(dic)

140153653660544

In [11]: id(new)

Out[11]: 140153653660544

In [12]: id(dic)

Out[12]: 140153653660544

In [13]: new["luenci"]='b'

In [14]: dic

Out[14]: {'luenci': 'b'}

   

\# 传入不可变类型

In [15]: a = 'luenci'

   

In [18]: def return_test2(x):

   ...:   print(id(x))

   ...:   return x

   ...:

In [19]: b = return_test2(a)

140153665839728

In [20]: id(a)

Out[20]: 140153665839728

In [21]: id(b)

Out[21]: 140153665839728