前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python函数参数传递机制

Python函数参数传递机制

作者头像
猫叔Rex
发布2022-01-24 13:44:25
7600
发布2022-01-24 13:44:25
举报
文章被收录于专栏:科学计算科学计算

Python3中有6中标准的数据类型:

  • Number(数字)
  • String(字符串)
  • List(列表)
  • Tuple(元组)
  • Set(集合)
  • Dictionary(字典)

其中Number、String、Tuple和Sets是不可变类型,List和Dictionary是可变类型。

什么是可变类型?什么是不可变类型?

1. 可变类型

  对不可变类型的变量重新赋值,实际上是重新创建一个不可变类型的对象,并将原来的变量重新指向新创建的对象(如果没有其他变量引用原有对象的话(即引用计数为0),原有对象就会被回收)。

  我们以Number类型为例,定义a=1,当a的值发生变化后,则a的内存地址发生了变化,用id()可查看变量的内存地址:

代码语言:javascript
复制
>>> a = 1
>>> id(a)
1503521232
>>> a = 2
>>> id(a)
1503521264

而如果令a=1,再令b=1,我们看a和b的内存地址:

代码语言:javascript
复制
>>> a = 1
>>> b = 1
>>> id(a)
1503521232
>>> id(b)
1503521232

但如果是两个大小相同的浮点数,发现它们并不是指向同个内存地址,这点和int类型不同(这与Python内存管理机制有关,Python对int类型和较短的字符串进行了缓存,无论声明多少个值相同的变量,实际上都指向同个内存地址)。

代码语言:javascript
复制
>>> a = 1.5
>>> b = 1.5
>>> id(a)
30347720
>>> id(b)
30347696
>>> a += 1
>>> a
2.5
>>> id(a)
30347576

2. 不可变类型

我们以list为例,当list的内容发生变化时,还是指向同个内存地址,因为list是可变类型,可以在原处修改。

代码语言:javascript
复制
>>> a = [1, 2, 3]
>>> id(a)
39059528
a.append(4)
>>> id(a)
39059528

当存在多个值相同的list变量时,他们分别指向不同的内存地址。

代码语言:javascript
复制
>>> a = [1, 2, 3]
>>> b = [1, 2, 3]
>>> id(a)
39060744
>>> id(b)
39059528

当把列表a直接赋给列表b时,他们指向同样的内存地址,因此当a改变时,b也随之改变。

代码语言:javascript
复制
>>> a = [1, 2, 3]
>>> b = a 
>>> a.append(4)
>>> b 
[1, 2, 3, 4]
>>> id(a)
39060936
>>> id(b)
39060936

3. 传参机制

  Python中有两种函数的传参机制:值传递和引用传递。看下面的例子会更加直观。

  • 值传递
代码语言:javascript
复制
def swap(x, y):
    x, y = y, x
    print('函数中 x = ', x, ' y = ', y)
    return x, y

x = 10
y = 20
print('函数调用前 x = %d, y = %d' % (x, y))
swap(x, y)
print('函数调用后 x = %d, y = %d' % (x, y))

打印结果如下:

代码语言:javascript
复制
函数调用前 x = 10, y = 20
函数中x = 20, y = 10
函数调用后 x = 10, y = 20

可以看到,我们在函数中对两个Number变量的值进行了交换,但函数运行之后,发现两个变量的值并未交换。

  • 引用传递

如果我们把输入的变量换成是列表:

代码语言:javascript
复制
def swapList(lst):
    lst[0], lst[1] = lst[1], lst[0]
    print('函数中 lst = ', lst)

lst = [1,2]
print('函数调用前 lst = ', lst)
swapList(lst)
print('函数调用后 lst = ', lst)

打印结果如下:

代码语言:javascript
复制
函数调用前 lst =  [1, 2]
函数中 lst =  [2, 1]
函数调用后 lst =  [2, 1]

可以看到,列表中的值确实发生了交换。

  是什么原因导致我们传递Number类型时没有交换成功,但传递List类型时就交换成功了。

  这是因为当我们传递Number类型时,swap函数的形参是实参的副本,也就是在函数内部会复制一份x和y,然后进行交换,所以实际中并没有交换实参x y的值。

  但对于可变类型,数据是存储在堆中,栈中只存储了引用,所以在修改形参数据时实参会改变。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-07-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 傅里叶的猫 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 可变类型
  • 2. 不可变类型
  • 3. 传参机制
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档