1 基本概念
在python中一切皆对象,但对象有可变对象与不可变对象之分。
可变与不可变指的是其内容是否可变。
- 可变对象
对象创建完之后内容可改变,但地址不会变
- 不可变对象
对象创建之后内容不可改变,如果改变其地址也会变
参考https://www.runoob.com/note/46684
2 可变对象
可变对象有:列表,字典,集合等
- 对于列表
l1 = [[1],1]
print(id(l1))
l1.append(2)
print(id(l1))
l1[0].append(2)
print(id(l1))
结果
2267960772104
2267960772104
2267960772104
id是对象的地址,是十进制的表示方式。对列表l1做了改变,但其地址并未变。
- 对于字典、集合
# dict
d1 = {"a":1,"b":2}
print(d1, id(d1))
d1["c"] = 3
print(d1, id(d1))
d1["a"] = 0
print(d1, id(d1))
# set
s1 = {1,2}
print(s1, id(s1))
s1.add(3)
print(s1, id(s1))
s1.remove(2)
print(s1, id(s1))
# 结果
{'a': 1, 'b': 2} 2575808202440
{'a': 1, 'b': 2, 'c': 3} 2575808202440
{'a': 0, 'b': 2, 'c': 3} 2575808202440
{1, 2} 2575808614472
{1, 2, 3} 2575808614472
{1, 3} 2575808614472
同样内容变了,地址没有变
3 不可变对象
有int,float,字符串,tuple
# 不可变对象
i = 1
print(i, id(i))
i +=1
print(i, id(i))
#结果
1 1931280880
2 1931280912
变量i存的是对象的引用
4 为什么要有可变与不可变之分
自认为是为了函数的参数传递问题,python只允许使用引用传递
5 函数传参-引用传递
函数外部变量,函数内部调用了,其外部变量会不会变
- 不加return
def change(a, b):
# a是int,b是列表
if not isinstance(a, int):
print("a不是int类型")
return -1
if not isinstance(b, list):
print("b不是list类型")
return -1
a +=1
b.append(4)
i = 1
l1 = [1,2,3]
print(i, id(i))
print(l1, id(l1))
# 结果
1 1932067312
[1, 2, 3] 2370243772168
1 1932067312
[1, 2, 3, 4] 2370243772168
change()函数增加是对a,b的改变。
从结果可以看出
- 不可变对象i,在函数内部改变,其内容和地址都不会变,实际上是函数内部的id对象改变了,只不过没有返回
- 可变对象l1,在函数内部改变,其内容改变了,地址没有变
上面是在没有接收返回结果的条件下,也就是没有return a,b
加return
def change2(a, b):
# a是int,b是列表
if not isinstance(a, int):
print("a不是int类型")
return -1
if not isinstance(b, list):
print("b不是list类型")
return -1
a +=1
b.append(4)
return a, b
m = 0
lis = [0, 0]
result1, result2 = change2(m,lis)
print("之前:", m, id(m), lis, id(lis))
print("之后:", result1, id(result1), result2, id(result2))
print(id(lis))
# 结果
之前: 0 1932067280 [0, 0, 4] 1561835406856
之后: 1 1932067312 [0, 0, 4] 1561835406856
1561835406856
不可变对象,接受返回对象后,其值可地址都改变了,这比较符合不可变对象的定义:不可变对象内容改变,地址改变
对于可变对象
- 用新的变量result2接受返回对象后,result2相对于原来的lis内容改变,地址不变
- 原来的变量lis的内容改变,地址没变
- 也符合可变对象的定义,内容改变,地址不变
那有个问题,新的变量result2和原来的变量lis地址和内容都一样,是同一个变量吗?改变其中一个变量的内容,另外一个会不会变?
验证:在原来的代码基础上增加
- 只改变lis
# result2和lis,一个改变另外一个会不会变
print("before: lis={0}, result2={1}".format(lis, result2))
lis.append("只改变lis")
print("只改变lis:lis={0}, result2={1}".format(lis, result2))
#结果
before: lis=[0, 0, 4], result2=[0, 0, 4]
只改变lis:lis=[0, 0, 4, '只改变lis'], result2=[0, 0, 4, '只改变lis']
从结果来看,只改变lis,result2也跟着改变
- 只改变result2
应该是两个都变
print("before: lis={0}, result2={1}".format(lis, result2))
result2.append("只改变result2")
print("只改变result2:lis={0}, result2={1}".format(lis, result2))
# 结果
before: lis=[0, 0, 4], result2=[0, 0, 4]
只改变result2:lis=[0, 0, 4, '只改变result2'], result2=[0, 0, 4, '只改变result2']
和预期一样,两个都改变
lis和result2都指向同一地址,内容都一样,类似与同一地址,不同标签
和列表的赋值操作差不多,即result2=lis
这要牵扯到可变对象的复制问题了
https://blog.youkuaiyun.com/u011630575/article/details/78599918
本文探讨了Python中的可变对象(如列表、字典和集合)与不可变对象(如整数、浮点数、字符串和元组)的概念。在Python中,可变对象在内容更改后地址不变,而不可变对象内容改变则会改变其地址。文章通过实例解释了函数参数传递中的引用传递,并分析了加不加return时对可变和不可变对象的影响,揭示了Python中对象赋值和复制的深层次理解。
5538

被折叠的 条评论
为什么被折叠?



