Python中类变量与成员变量相互影响的原因超详细解释

Python类变量与成员变量相互影响的原因超详细解释

今天看到了这样一篇文章:http://www.jb51.net/article/112525.htm

讲的是类变量和成员变量的影响原因,但原文并没有讲明详细原因,只是讲清楚了类变量与成员变量影响的结论,由于前几日看了《Python学习手册》这本书了解了一下Python的数据储存机制,然后自己想并且试验了一下,大致找到了原因,由于作者水平有限如原因有错请多原谅并指出,感激不尽。

先科普一下Python的数据储存机制,知道的就跳过往下看吧,Python的变量不用声明且可以随意赋值,因为Python的变量其实是类似C语言中指针的包装,例如python中

a=3

-------------------------------------------------------------------------------------------------------------------------------------------------

所以在python中变量皆为指针。那么,看看原文章中的例子

class A:
    x = []
    y = 0

    def __init__(self):
        pass

    def add(self):
        self.x.append('1')
        self.y+=1
a=A() 
print a.x,a.y
print A.x,A.y

a.add()
print a.x,a.y
print A.x,A.y

b=A() 
print b.x,b.y
print A.x,A.y

输出结果为

  •  [] 0
  •  [] 0

  •  ['1']1
  •  ['1']0

  •  ['1']0
  •  ['1']0

-------------------------------------------------------------------------------------------------------------------------------------------------

先来从头到尾分析一遍:因为首先生成a这个对象并没有实例变量(__init__没有参数),所以虽然a实例和A类为两个不同内存地址,但是a.x和A.x却都是引用类A变量x的内存地址(类创建的时候一块内存地址出现了[]这个值,由于后续生成实例并没有赋值操作,所以整个内存中有且仅有一个[]值,又因为变量为指针,所以这个两个变量同时指向[]的内存地址)


所以当a调用a.add方法时,self传的又是自身,相当于执行了a.x.append('1'),而a.x与A.x指向的内存相同,由于a.append函数并不改变变量a指向的内存地址,而是改变内存地址中的值(相当于在a所指的内存地址中的原值进行操作即对[]进行操作)

a=[]
print(id(a))
a.append('a')
print(id(a))

输出结果为两个相同的值,即append函数是对原值进行了操作。所以A类对象本身值被改变,以至于接下来生成的b实例的b.x值也被改变,那么为什么A.y这个值却没有改变呢?

-------------------------------------------------------------------------------------------------------------------------------------------------

下面分析y这个类变量,给你们下面这段代码你们应该就懂了

i = 1
print(id(i))
i +=1
print(id(i))
输出结果是两个不同的值    原理是假设1这个值被存放在0xF0这个内存空间,进行i+=1的时候,1+1=2,2这个值生成并被放在假设0xFF这个地址内,然后i从指向0xF0转为指向0xFF,而不是2这个值覆盖原地址。

根据这个结论来讨论我们的问题a.add()的函数进行了self.y+=1的操作,虽然self.y 和 a.y 和 A.y为同一个内存地址,但是self.y+=1却只是改变了self.y的指向,代码执行后self.y指向了另一块内存地址而A.y指向的内存地址没变,相当于创建了一个副本,所以在接下来生成b实例的时候b.y的值还是0,因为类变量y指向内存空间的值并没有改变。

  • 1
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值