|
|
51CTO旗下网站
|
|
移动端

3.1.1 函数参数传递

《自学Python:编程基础、科学计算及数据分析》第3章Python 进阶,在本章中,我们将学习 Python的一些进阶用法,包括函数的进阶,迭代器、生成器、装饰器、上下文管理器的使用,以及 Python中的变量作用域。本节为大家介绍函数参数传递。

作者:李金来源:机械工业出版社|2018-05-03 21:44

3.1.1 函数参数传递

1.参数的传递机制

在 Python中,函数参数的传递机制与赋值机制一样,其本质都是共用内存地址,不会真正地复制对象。这种共享内存的方式叫做引用传递。

引用传递(Call By Reference)模式指的是函数在调用过程中,参数与实际传入的对象共享同一块内存地址。
为了进一步理解引用传递的本质,我们使用id()函数来进行简单说明。

定义如下函数:

  1. In [1]: def f(x):  
  2.    ...:     return id(x)   
  3.  
  4.    ...: 

对于给定的参数x,该函数返回出参数 x的对应的内存地址。

我们将函数作用在一个对象上:

  1. In [2]: a = 1.2  
  2. In [3]: id(a)  
  3. Out[3]: 30089560  
  4. In [4]: f(a)  
  5. Out[4]: 30089560 

函数 f(a)的返回值与 a的内存地址是一致的。

当我们调用函数 f时,Python并没有将 a的值复制一份传给参数 x,而是让参数 x与 a共享了同一块内存。也就是说,x和 a是同一个对象。

再看传入列表作为参数的情况:

  1. In [5]: b = [1, 2, 3]  
  2. In [6]: id(b)  
  3. Out[6]: 140386741246144  
  4. In [7]: f(b)  
  5. Out[7]: 140386741246144 

共享同一个对象的机制意味着,我们可以在函数中修改传入参数的值。

例如,我们定义这样的一个函数,对于参数x,让x[0]变为999,并返回修改后的x:

  1. In [8]: def mod_f(x):  
  2.    ...:      x[0] = 999  
  3.    ...:      return x  
  4.    ...: 

对列表 a应用这个函数,Python会先让 x指向 a所在的内存。由于 x和 a共享同一个对象,修改x[0]会让 a的值相应改变:

  1. In [9]: a = [1, 2, 3]   
  2. In [10]: mod_f(a)   
  3. Out[10]: [999, 2, 3]   
  4. In [11]: a   
  5. Out[11]: [999, 2, 3] 

假设我们在函数中给参数 x赋了一个新值,如另一个列表。根据赋值机制,虽然 x指向一个新的内存位置,但原来的变量不会改变:

  1. In [11]: def no_mod_f(x):  
  2. ...: x = [4, 5, 6]  
  3. ...: return x  
  4. ...:  
  5. In [12]: b = [1, 2, 3]  
  6. In [13]: mod_f(b)  
  7. Out[13]: [4, 5, 6]  
  8. In [14]: b  
  9. Out[14]: [1, 2, 3] 

2.默认参数的传递

有默认参数的情况下,Python会在定义函数时,预先为默认参数分配内存,每次调用默认参数时,Python会从这个预先分配好的内存地址得到这个默认参数,以免每次生成一个额外的默认参数。这样做能够节约一定的空间,不过也可能会得到一些与直觉不符的结果。

例如,考虑这样的函数 f,该函数接受一个参数x,该参数的默认值为空列表:

  1. In [15]: def f(x = []):  
  2. ...: x.append(1)  
  3. ...: return x  
  4. ...: 

如果我们不给 f传递参数,直觉上它应该返回列表[1]。实际上,由于默认参数始终使用同一个列表,每次调用默认参数时,函数中的.append()方法改变了这个列表,因此,这个列表会随之改变:

  1. In [16]: f()  
  2. Out[16]: [1]  
  3. In [17]: f()  
  4. Out[17]: [1, 1]  
  5. In [18]: f()  
  6. Out[18]: [1, 1, 1] 

因此,我们在使用默认参数时,应当尽量减少使用可变的容器类型,如列表、字典等作为函数的默认参数,以免出现意料之外的结果。

这种机制并不是 Python设计上的问题,在某些情况下,这样的机制有时候还能方便我们进行操作,如提供对计算结果的缓存等。

喜欢的朋友可以添加我们的微信账号:

51CTO读书频道二维码


51CTO读书频道活动讨论群:365934973

【责任编辑:book TEL:(010)68476606】

回书目   上一节   下一节
点赞 0
分享:
大家都在看
猜你喜欢

读 书 +更多

网管第一课——计算机网络原理

本书是《网管第一课》系列图书中的第一本,是专门针对高校和培训机构编写的,其主要特点是内容细而精、针对性强。书中内容全是经过精心挑选...

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊