刚学python,学到了有关于类和对象的地方。对一个概念有点模糊,后来通过实践编码找到一定规律
在python中
class test(object): id=2 name='tt' list=['tt','dd'] def change(self,newA,new_id): self.id=new_id self.age=newA return self.age t1 = test() t1.change(21, 3) print t1.id #3 t2 = test() t2.age = 200 #对象属性 print t2.id #2 t1.id=100 print t2.id #2 #改变list的值 t1.list[0]='dd' print t1.list #['dd', 'dd'] print t2.list #['dd', 'dd'] #对象属性 print t1.age #21 print t2.age #200
在这里,t1对象修改了id值,但是并不影响t2对象中的id值。通过t1对象改变list的值,其他对象对应的值也发生了改变。
为什么会这样呢?类属性分为两种:属性是immutable的(比如整数、字符串)。属性是mutable的话(比如list)
在更改对象属性时,如果属性是immutable的,该属性会被复制出一个副本,存放在对象的__dict__中。你可以通过下面的方式查看:
print t1.__class__.__dict__
print t1.__dict__
输出分别为
{‘__module__‘: ‘__main__‘, ‘name‘: ‘tt‘, ‘list‘: [‘dd‘, ‘dd‘], ‘__doc__‘: None, ‘__dict__‘: <attribute ‘__dict__‘ of ‘test‘ objects>, ‘__weakref__‘: <attribute ‘__weakref__‘ of ‘test‘ objects>, ‘id‘: 2, ‘change‘: <function change at 0xb723eb1c>}
{‘age‘: 21, ‘id‘: 100}
注意到类中和对象中各有一个id。一个为2, 一个为100。所以我们在查找a.Age的时候,会先查到对象的__dict__的值,也就是100。
但mutable的类属性,在更改属性值时,并不会有新的副本。所以更改会被所有的对象看到。
你可能会发现在对象的dict中多了一个age属性,这个属性就是对象属性,对象独有。
同理:
print t2.__class__.__dict__
print t2.__dict__
{‘__module__‘: ‘__main__‘, ‘name‘: ‘tt‘, ‘list‘: [‘dd‘, ‘dd‘], ‘__doc__‘: None, ‘__dict__‘: <attribute ‘__dict__‘ of ‘test‘ objects>, ‘__weakref__‘: <attribute ‘__weakref__‘ of ‘test‘ objects>, ‘id‘: 2, ‘change‘: <function change at 0xb72f0b1c>}
{}
说到这里,稍微总结一下:
1.age是对象属性,每一个对象独有的。修改对象属性不影响其他对象的属性值
2.每一个对象关联的class都有一个字典,每个对象初始化时,也存在一个字典,如果没有对对象中的属性赋值,该字典为空。
当使用对象.属性名来赋值的时候,如果是类中immutable类型属性,那么这就是所谓的副本。字典中就增加相应的属性和属性值。
如果是类中的mutable的话(比如list),该对象的字典中不会增加这个mutable属性。但是会修改类的字典的相应的属性值。
3.如果使用class.类属性名来修改类属性值的化,如果对象的字典为空的化,也就是还没有为通过对象名.属性名来赋值属性,那么对象.属性名将是class字典中的属性。
4.对象名.属性名 首先从自己对象字典中找属性,如果没有的话再去class字典中找。
浅析python中的类变量和对象变量