python可变对象与不可变对象

转载 2018年04月16日 19:51:25

转自:http://mp.weixin.qq.com/s/vj9IxEHN815eASmWlDSzMg

Python中有可变对象和不可变对象之分。可变对象创建后可改变但地址不会改变,即变量指向的还是原来的变量;不可变对象创建之后便不能改变,如果改变则会指向一个新的对象。


Python中dict、list是可变对象,str、int、tuple、float是不可变对象。

来看一个字符串的例子

a = "hello"
print(id(a))  # 输出 140022851974560

a[0]="a"  # 抛出异常:TypeError: 'str' object does not support item assignment

a = a + " world"
print(id(a))  # 输出 140022850763824

上面的例子里,修改a指向的对象的值会导致抛出异常。

执行 a = a + " world"时,先计算等号右边的表达式,生成一个新的对象赋值到变量a,因此a指向的对象发生了改变,id(a) 的值也与原先不同。


再来看一个列表的例子

a = [1,2,3]
print(id(a))  # 输出 140022851303976

a[0]=5
print(a)      # 输出 [5, 2, 3]
print(id(a))  # 输出 140022851303976

a.append(5)
print(a)      # 输出 [5, 2, 3, 5]
print(id(a))  # 输出 140022851303976

b = a
print(id(b))  # 输出 140022851303976

b[0] = 6
print(b)      # 输出 [6, 2, 3, 5]
print(a)      # 输出 [6, 2, 3, 5]

c = b[:]
print(id(c))  # 输出 140022851006760
print(id(b))  # 输出 140022851303976

c.append(7)
print(c)      # 输出 [6, 2, 3, 5, 7]
print(b)      # 输出 [6, 2, 3, 5]

上面对a修改元素、添加元素,变量a还是指向原来的对象。

将a赋值给b后,变量b和a都指向同一个对象,因此修改b的元素值也会影响a。

变量c是对b的切片操作的返回值,切片操作相当于浅拷贝,会生成一个新的对象,因此c指向的对象不再是b所指向的对象,对c的操作不会改变b的值。


理解了上面不可变对象和可变对象的区别后,我们再来看一个有趣的问题

class Group(object):
   def __init__(self, group_id, members=[]):
       self.group_id = group_id
       self.members = members
   def add_member(self, member):
       self.members.append(member)

group1 = Group(1)
group1.add_member("Wang")
group1.add_member("Sun")
print(id(group1))        # 输出 140280211197776
print(group1.members)    # 输出 ['Wang', 'Sun']

group2 = Group(2)
group2.add_member("Zhang")
group2.add_member("Li")

print(id(group2))        # 输出 140280211197840
print(group1.members)    # 输出 ['Wang', 'Sun', 'Zhang', 'Li']
print(group2.members)    # 输出 ['Wang', 'Sun', 'Zhang', 'Li']

明明group1和group2是不同的对象(id值不同),为什么调用group2的add_member方法会影响group1的members?

其中的奥妙就在于__init__函数的第二个参数是默认参数,默认参数的默认值在函数创建的时候就生成了,每次调用都是用了这个对象的缓存。我们检查id(group1.mebers)和id(group2.members),可以发现他们是相同的

print(id(group1.members))  # 输出 140127132522040
print(id(group2.members))  # 输出 140127132522040

所以,group1.members和group2.members指向了同一个对象,对group2.members的修改也会影响group1.members。

好了,问题来了,怎样改代码才能解决上面默认参数的问题呢?


其实很简单,只要传入None作为默认参数,在创建对象的时候动态生成列表,如下

class Group(object):
   def __init__(self, group_id, members=None):
       self.group_id = group_id
       if members is None:
           self.members = []

   def add_member(self, member):
       self.members.append(member)

这样对于不同的group对象,它们的members也是不同的对象,所以不会再出现更新一个group对象的members也会更新另外一个group对象的members了。


Python学习笔记——可变对象和不可变对象

转载自:http://www.cnblogs.com/evening/archive/2012/04/11/2442788.html
  • taohuaxinmu123
  • taohuaxinmu123
  • 2014-09-02 16:40:47
  • 14213

可变对象 vs 不可变对象(Python)

Python 在 heap 中分配的对象分成两类:可变对象和不可变对象。所谓可变对象是指,对象的内容是可变的,例如 list。而不可变的对象则相反,表示其内容不可变。 不可变对象:int,string...
  • lanchunhui
  • lanchunhui
  • 2016-08-27 22:27:57
  • 1050

Python中可变对象和不可变对象

之前写了FPGrowth的代码,写得非常恶心,觉得和C语言、C++的工程文件很不相同。其中就有关于传引用、传值的疑问。截一段Leetcode的代码这题好像是Leetcode 93附近的一道 获得二叉树...
  • u013007900
  • u013007900
  • 2017-02-13 12:56:21
  • 1135

python学习之路——函数关于可变对象和不可变对象问题

可更改(mutable)与不可更改(immutable)对象 在 python 中,整数、字符串和 元组是不可更改的对象,而 列表,字典 等则是可以修改的对象。 不可变类型:变量赋值 a=5 后再...
  • eml_jw
  • eml_jw
  • 2017-05-04 20:05:31
  • 445

python的可变和不可变对象

python的对象分为可变对象(mutable)和不可变对象(immutable) 不可变对象(immutable)包括:常数、字符串、元组和不可变集合(frozensets) 可变对象包括:列表...
  • midion9
  • midion9
  • 2016-04-29 14:59:36
  • 300

java中可变对象与不可变对象

可变对象(mutable Objects),不可变对象(Immutable ojbects),那么他们有什么区别呢? 不可变对象意味着这个对象是final的,对象中所有的公共属性是final的。同时说...
  • a1523407
  • a1523407
  • 2017-03-17 16:11:10
  • 1250

【Python学习日记】dic和set 以及什么是 不可变对象

转载自 http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014316779353...
  • renxingzhadan
  • renxingzhadan
  • 2016-06-22 11:06:28
  • 1284

Java不可变对象

不可变对象是指一个对象的状态在对象被创建之后就不再变化。不可变对象对于缓存是非常好的选择,因为你不需要担心它的值会被更改。 创建一个不可变类: 将类声明为final,所以它不能被继承;将所...
  • Tian_Ex
  • Tian_Ex
  • 2016-01-10 16:27:28
  • 4181

python 传值 传引用 可变对象 不可变对象 的区别与联系

可变对象 与 不可变对象我们知道在python中一切皆对象。在python世界中可以把对象大体分成两大类:不可变对象:数字(int,float, double)、字符串、元组(tuple)、funct...
  • fm_VAE
  • fm_VAE
  • 2018-03-06 23:44:11
  • 37
收藏助手
不良信息举报
您举报文章:python可变对象与不可变对象
举报原因:
原因补充:

(最多只允许输入30个字)