浅析python中的类变量跟对象变量

浅析python中的类变量和对象变量

刚学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字典中找。