Python中mutable与immutable和二维列表的初始化问题

导读:本篇文章讲解 Python中mutable与immutable和二维列表的初始化问题,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

考虑对二维列表进行初始化,这个问题在上一篇中已经讨论过了,例如,初始化一个shape为(3,3)的二维列表,正确的写法是这样的:

a = [[None] * 3 for i in range(3)]
print(a)

a[0][0] = 1
print(a)

#经过测试没有问题
# 输出:
#[[None, None, None], [None, None, None], [None, None, None]]
#[[1, None, None], [None, None, None], [None, None, None]]

但是,如果写成这样:

a = [[None] * 3] * 3
print(a)

# 输出 : [[None, None, None], [None, None, None], [None, None, None]]

看起来像是没有问题,实际上,如果进行赋值操作,就会发现问题:

a[0][0] = 1
print(a)

# 输出:[[1, None, None], [1, None, None], [1, None, None]]

结果三行的对应位置的元素全都改变了!(就因为这个问题找了好长时间的bug… =_=|||)
后来知道,这个问题与Python中数据类型的分类有关,所以在这里记录一下,存个档。

步入正题,在Python中有一句话:万物皆对象(好像OOP都是这么说。。),在Python中所写的一切都可以看作是一个对象,比如定义的整数、浮点数以及列表,元组等,但是这些对象也有区别,这些对象,有些属于mutable(可变),有些则是属于immutable(不可变),这是什么意思呢?先看一个例子:

# 这里定义一个整数  id()函数可以查看对象的内存位置
a = 3
print(id(a))
a += 1
print(id(a))

#输出:
#  140730246819648
#  140730246819680

# 接下来定义一个列表:
a = [1,2,3]
print(id(a))
a[0] = 100
print(id(a))

# 输出:
#  2744865681864
#  2744865681864

通过对比,不难发现,对数值,比如整数、浮点数进行改变,内存的位置会发生改变,但是对列表,字典之类的进行改变,则不会改变内存位置。
实际上,对于整数、浮点数,改变值的时候,实际上是新开辟了一块内存,然后把加法的结果填充到这快内存中,然后再把a指向这块新的内存。关于这个,可以看一下廖雪峰老师的文档:数据类型和变量
这里提到了“指向”,如果学过C或者C++,可能会想到指针或者引用,再Python中也有说引用的,那么这里就可以看出两种语言的“引用”是不同的了,C++中,对引用的数据进行改变,这个位置应该是不变的,而再Python中,显然,就像上面,相当于改变了“引用”,而不是内存的数据。
这里可能有点绕,不过这里也就是所说的mutable和immutable的问题了,在Python中,immutable的类型有整数、浮点数、字符串以及元组等等,而mutable的类型有list,dict以及自定义的类型。

那么回到上面一开始的问题中,知道了list是mutable的,所以在创建的时候,并不是赋值到了新的位置,只是创建了三个指针(a[0], a[1], a[2])指向了同一块内存而已,所以,改变其中一个的某个元素,会对所有的元素产生影响,。

参考资料:

关于python中immutable对象与mutable对象的问题

python mutable 和 immutable

python学习之—mutable and immutable

python变量赋值(可变与不可变)

以上~

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/116718.html

(0)
seven_的头像seven_bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!