1.之前疑惑:
本人刚从c转到python,一直有个问题,为什么python为什么会有可更改变量list和不可更改变量的tuple区分,他们的实质不是一样的吗?都是数组?直到看到他们在函数传参的时候,才清楚为什么要有这两者,其实答案显而易见,前者可更改,后者不可更改,保证了数据的安全性,虽然听着像废话,但当你试图去深入了解的时候,就会发现这种设计有多么巧妙了
2.原理介绍(对比C和Python):
C,C++局部变量和全局变量对变量的作用域做了严格限定
在所有函数外部定义的变量称为全局变量(Global Variable),它的作用域默认是整个程序。所以不管是在函数内还是函数外,修改它的值都会变化
定义在函数内部的变量称为局部变量(Local Variable),它的作用域仅限于函数内部, 出了函数再使用就会报错
在 python 中,类型属于对象,对象有不同类型的区分,变量是没有类型的:
a = [1, 2, 3]
a = "hello!"
上面代码中,对象[1,2,3]是list类型,对象"hello!"是string类型,a是指针(对象的引用),可以指向[1,2,3],也可以指向"hello!"
在 python 中,strings, tuples, 和 numbers 是不可更改的对象,而 list,dict 等则是可以修改的对象。
不可变类型:变量赋值 a=5 后再赋值 a=10,这里实际是新生成一个 int 值对象 10,重新分配了内存,再让 a 指向它,而 5 被丢弃,不是改变 a 的值
可变类型:变量赋值 a=[1,2,3,4] 后再赋值 a[2]=6则是将 list a 的第三个元素值更改,指针a指向的地址没有动,只是列表对象内部的一部分值被修改了
有了这样的设定后,python在函数传参时,传递的是对象的指针,如果在函数里面修改了可更改变量,则原变量的值发生改变
3.代码分析:
3.1.不可变参数重新赋值
#!/usr/bin/python3
a = 1
print(a)
print(id(a))
# 1
# 548524859704
a = 2
print(a)
print(id(a))
# 2
# 548524859736
不可变参数重新赋值,重新分配内存保存int新对象,变量值发生变化
3.2.可变参数重新赋值
#!/usr/bin/python3
a = [1,0]
print(a)
print(id(a))
# [1, 0]
# 5483868732244
a[0]= 2
print(a)
print(id(a))
# [2, 0]
# 548386873224
可变参数重新赋值,不重新分配内存,变量值发生变化
3.3.函数传递不可变参数
#!/usr/bin/python3
# 函数内更改不可变参数
def val_change(a):
a = a + 1
a = 110
print(a)
print(id(a))
# [110, 0]
# 547681083272
val_change(a)
print(a)
print(id(a))
# [110, 0]
# 547681083272
函数传递不可变参数 ,重新赋值,不重新分配内存,变量值不发生变化
3.4.函数传递可变参数
#!/usr/bin/python3
# 函数内更改list
def val_change(a):
a[0] = a[0] + 1
a = [110,0]
print(a)
print(id(a))
# [110, 0]
# 547681083272
val_change(a)
print(a)
print(id(a))
# [111, 0]
# 547681083272
函数传递可变参数 ,重新赋值,不重新分配内存,变量值发生变化