这个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