本来正在写递归,但是又一次遇到了关于python 的小问题,先记录下来,以备不时之需(话说这已经是我写的第二篇传参问题了啊喂,,,)。
附上之前遇到的问题:
下面我们分三种情况来讨论:
case1,参数为不可变对象(数值类型(int和float)、字符串str、元组tuple都是不可变类型),python 通过值传递:
def change(val):
print('val ',id(val))
val += 10
print('val ',id(val))
nums = 20
print(nums)
print('nums',id(nums))
change(nums)
print('nums',id(nums))
print(nums)
运行结果如下:
20
nums 2016306105392
val 2016306105392
val 2016306105584
nums 2016306105392
20
这个应该很好理解,我仿佛已经听到了大家在说 “naive” 的声音。
case2,参数为可变对象(列表list、字典dict、集合set是可变类型),python 通过引用传递:
def change(val):
print('val ',id(val))
val.append(10) #大家可以留意一下这句话
print('val ',id(val))
nums = [0, 1]
print(nums)
print('nums',id(nums))
change(nums)
print('nums',id(nums))
print(nums)
运行结果如下:
[0, 1]
nums 2802784706440
val 2802784706440
val 2802784706440
nums 2802784706440
[0, 1, 10]
可以非常清楚的看到,nums的值发生了改变,而函数当中的val,其实就是nums。
case3,参数为可变对象,但传递过去的参数又指向了其他对象:
def change(val):
print('val ',id(val))
val = val + [10] #这句是关键,经过该赋值语句,此 val 已非彼 val
print('val ',id(val))
nums = [0, 1]
print(nums)
print('nums',id(nums))
change(nums)
print('nums',id(nums))
print(nums)
运行结果如下:
[0, 1]
nums 2248343854984
val 2248343854984
val 2248343905672
nums 2248343854984
[0, 1]
我们可以看出,若传递过去的参数指向了其他对象,则对该对象的操作并不影响原变量的对象值。也就是说,刚传进函数时,val 和 nums 是一样的,但是经过了赋值之后,val发生了改变,此时 val 指向了与 nums 不同的内存变量,所以最终 nums 还是我们熟悉的那个 nums,但val 已经不是我们认识的 val 了~
其实道理也极其简单,第三种情况就是第二种情况的特殊例子,如果不好理解的话,我可以把代码换成如下形式:
def change(val):
print('val ',id(val))
new_val = val + [10] #其他的不用看了,变的还是这一行代码
print('new_val ',id(val))
nums = [0, 1]
print(nums)
print('nums',id(nums))
change(nums)
print('nums',id(nums))
print(nums)
这下是不是清晰了一些呢?我虽然把 nums 传递过去了,但是我并没有改变它的值,我只是用它做了一些计算而已,那么 val 在函数当中都没有发生变化,又怎么会影响到 nums 呢?
欢迎大家关注小编,或者热心点赞~
你们的每一个赞和关注,都是我骄傲的资本(/斜眼笑ing)
网友评论