一 关于局部变量整体变量的理解 以及something about不可变对象
def ChangeInt(a):
... a=10
...
b=2
ChangeInt(b)
print(b)
2
这个不可变对象的实例让我产生了疑惑,于是我做了如下:
def ChangeInt(a):
... a=10
...
a=2
ChangeInt(a)
print(a)
2
这个其实很好理解,因为a=10只是个局部变量,也没有return无法对外部造成影响。哪怕我做如下操作:
def ChangeInt(a):
... a=10
... return a
...
a=2
ChangeInt(a)
10
print(a)
2
改变的依旧是局部变量内部的值,与外面的那个a无关。但是当我继续:
def ChangeInt(a):
... print(a)
... a=10
... print(a)
...
a=2
ChangeInt(a)
2
10
print(a)
2
可以推测,在函数内部,有一个先把函数外部的a代入函数内部,再根据函数命令改变其值的过程;外部的a依旧不受影响
那么回到第一个例子:
def ChangeInt(a):
... a=10
...
b=2
ChangeInt(b)
print(b)
2
是否也有一个:
b=2
a=b=2
a=10的过程?
为了验证我的猜想。。。
def ChangeInt(a):
... print(a)
... a=10
... print(a)
... print(b)
...
b=2
ChangeInt(a)
2
10
2
print(b)
2
可见过程中确实存在一个a=b=2的过程,然后10被赋值给了a(我也不知道为啥我要把这事儿整得那么复杂)。
二 关于python function中return,以及list作为可变对象实例的事例
def changeme(mylist):
... mylist.append([1,2,3,4])
... return
...
mylist=[1,2]
changeme(mylist)
mylist
[1, 2, [1, 2, 3, 4]]
- 光有return只结束function不返回任何值
- list作为一个可变对象实例不论结果是否被返回,它的值在函数内外是被统一的,即在函数内修改后函数外部的值也会受到影响。
for example:
def nano(myint):
... myint += 2
... return
...
myint=3
nano(myint)
myint
3
another example:
def nano(myint):
... myint += 2
... return myint
...
myint=3
nano(myint)
5
myint
3
由上述两例可见,当function中return了一个具体对象时,召唤函数直接返回了这个return的对象的值
而以int为例的不可变对象在function中,传递的只是a的值,没有影响a对象本身。在 fun内部修改 a 的值,只是修改了另一个复制的对象。
三 不可变对象存储与可变对象存储空间的差异
一个神奇的现象:
x=1
y=1
x is y
True
检查xy存储地址
print(hex(id(x)))
0x7fff442d7100
print(hex(id(y)))
0x7fff442d7100
可以发现它们存储地址相同,即这个1被同时赋值给了x和y
x="a"
y="a"
x is y
True
print(hex(id(x)))
0x2093ab6fbb0
print(hex(id(y)))
0x2093ab6fbb0
同理字符串
然而当我们把对象改为可以编辑的list的时候:
a=[1,2,3]
b=[1,2,3]
a is b
False
print(hex(id(a)))
0x2093ab97d88
print(hex(id(b)))
0x2093add17c8
可以发现哪怕是内容一样的list,两者的存储地址依旧是不同的。因为a和b是可被更改的。
而xy是指向同一个值的,它不需要在每次赋值之时开拓一片存储空间,只需要将变量指向现有的值;而对于list而言,则是需要给每一个list一个存储空间,以适应每一个list都会被改变的特性。
从本质上看,前者(int,string)在函数中复制了一个对象;而后者(list,set)在函数中仍旧指向原来的存储地址。
论我是如何把自己讲晕的:)