8. python函数传递值还是引用

这个blog是用来记录python函数到底传递的是引用还是值

  • is 和 == 的区别
  • tuple到底是不是不可变的…
  • 变量的本质
  • 函数传递是引用传递
1. is 和 ==的区别

==是表示值相同,但是不一定是同一块内存。而is是表示同一块内存地址,则值肯定相同。

  • 先举个简单的例子:
a = [1, 2, 3]
b = a
print('Address of a: {}, Address of b: {}'.format(id(a), id(b)))
# Address of a: 140262389525768, Address of b: 140262389525768
# 所以可以看出a和b指向的是一块内存,则 a is b
print(a is b)  # True
  • 深度探索 == 和 is
    下面举个例子:
a = 1
b = 1
print("a==b ? {}, a is b ? {}".format(a==b, a is b))
# a==b ? True, a is b ? True

a = 11111
b = 11111
print("a==b ? {}, a is b ? {}".format(a==b, a is b))
# a==b ? True, a is b ? True
# 目前尝试了[-5, 无穷],都是使用的相同的内存。这是为了省内存,因为内存中只需要存在一个变量。
# 同样的字符串也是,内存中只保留一个变量。

总结: 总结的不够完善,需要专门去了解python缓存池
1. 实际上,为什么有些变量可以共用一块内存呢,是因为python有缓冲池。

  • 对于整数,最小的整数为-5可以共用内存,-6就需要每次都要申请内存。目前测试的到的最大整数为5x10^90
  • 对于string,可以共用一块内存,因为string是不可以改变的。
2. tuple到底能不能改变?

首先要明白tuple不可改变指的是,tuple中的元素不能进行赋值,举例:

a = ([1], [2])
a[0] += [2]
print(a)
TypeError: 'tuple' object does not support item assignment
# 在这个例子中,+=表示两个过程,先加再赋值,
# 虽然a已经改变为([1, 2], [2]),但是还会报不能assign的错误(即使是同样的地址)
# 说明加是没有报错的。

虽然tuple不能赋值,但是可以append, 或者是in-place的修改

a = ([1], [2])
a[0].append(2)
print(a)   # ([1, 2], [2])  
3. 变量的本质

在python中,变量也是对象的引用,变量存储的是对象的地址
变量位于栈内存
对象位于堆内存
变量相当于对象的门牌号,或者是引用。变量可以通过这个引用来改变对象的值,也可以通过这个引用访问对象。

4. 函数传递是引用传递

结论: 实际上函数的传递,不管是可变变量还是不可变变量,传递的都是引用

  • 首先第一个结论: 传递的都是引用 , 看代码
    因为变量和穿进去的变量的地址是一样的说明是一块内存,所以是引用,指向的是同一块内存
def print_variable_id(a):
	print('传入的变量地址为: {}'.format(id(a)))
a = [1, 2, 3] # 可变对象
b = -55  # 不可变对象

print('a的地地址为 {}'.format(id(a)))
print_variable_id(a)

print('b的地址为{}'.format(id(b)))
print_variable_id(b)
  • 传递不可改变的对象是‘值传递’,不会改变函数外面的值,实际上是一种假象
def print_variable_id(a):
	a = 2
	print('修改变量后的地址为: {}'.format(id(a)))
a = 1
print('a的地址为 {}'.format(id(a)))
print_variable(a)
print('调用函数后,a的地址为 {}'.format(id(a)))

a的地址为 10853632
修改变量后的地址为: 10853664
调用函数后,a的地址为 10853632

首先要搞明白的是assign在python中是什么含义,assign表示变量和对象进行绑定,是换了指向,即使是可变变量也是一样的,如果在函数中进行赋值,函数外的变量也不会改变的。

def print_variable_id(a):
    a = 2  # 赋值会改变变量的地址。
    print('传入的变量地址为: {}'.format(id(a)))
a = [1, 2, 3]
print('a的地址为 {}'.format(id(a)))
print_variable_id(a)
print('调用函数后,a的地址为 {}'.format(id(a)))

而如果通过引用变量进行修改可变变量则结果就会变化,

def print_variable_id(a):
    a[2] = 10000  # 原地进行修改,不改变变量的地址
    print('传入的变量地址为: {}'.format(id(a)))
a = [1, 2, 3]
print('a的地址为 {}'.format(id(a)))
print_variable_id(a)
print('调用函数后,a的地址为 {}'.format(id(a)))

a的地址为 140527304391944
传入的变量地址为: 140527304391944
调用函数后,a的地址为 140527304391944
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值