1

一 关于局部变量整体变量的理解 以及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]]
  1. 光有return只结束function不返回任何值
  2. 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)在函数中仍旧指向原来的存储地址。

论我是如何把自己讲晕的:)


robinhhu
1 声望2 粉丝