python中的类属性和实例属性
面向对象语言中,一般会有“静态变量”,也就是给整个类共享的变量,如C++,java中static修饰的变量。但是在 python 中并没有 static 这个关键字,实现类似功能需要依靠python中的类属性和实例属性的语法特点。本文主要就是讲述这两种属性的区别。
在讲述之前,需要清楚下面两个事实: 1)python
中类创建的对象叫实例
2)类和实例均是对象,均有自己的对象属性,可通过__dict__
查看
下面先看一个例子: 1
2
3
4
5
6
7
8
9
10
11class TestAttribute:
content = []
def addContent(self,x):
self.content.append(x)
if __name__ == '__main__':
t1 = TestAttribute()
t2 = TestAttribute()
t1.addContent('t1')
print 'object t1:', t1.content, t1.__dict__
print 'object t2:', t2.content, t2.__dict__
输出结果: 1
2object t1: ['t1'] {}
object t2: ['t1'] {}
那假如各个实例要有自己独立的变量的?也很简单,**只需要在类的构造函数(也就是__init__函数)为变量赋值即可.**
1 | class TestAttribute: |
输出的结果如下所示: 1
2object t1: ['t1'] {'content':['t1']}
object t2: [] {'content':[]}
从结果可知,现在的t1,t2的变量独立了。那原因是什么呢?
原因是Python中对象属性的获取是按照从下到上的顺序来查找属性
怎么理解上面这句话呢?以上面代码为例,类和实例的关系如下所示:
1
2
3
4 TestAttribute
____|____
| |
t1 t2t1.content
时,python
解析器会先查看对象 t1
中是否有content这个属性,有的话输出这个属性的值,没有的话就往上查找
TestAttribute 中是否有这个属性并输出。
在上面的例一中,因为t1和t2的属性均为空,所以输出 t1.content 和 t2.content时实际上是输出 TestAttribute 的属性。又因为 TestAttribute 的 content 属性被修改了 t1 修改了,所以最后输出的的 t1.content 和 t2.content 内容一致。
而在例二中,因为在构造函数中的为content复制的操作使得每个被创建的实例均有自己的content属性,所以
t1 修改 content 时查到自己有content的属性,就只会修改自己的
content。不影响t2 的 content 和 TestAttribute 的
content。这个可以从下面的例子看出,假如将例二的代码修改成如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17class TestAttribute:
content = []
def __init__(self):
self.content=[]
def addContent(self,x):
self.content.append(x)
if __name__ == '__main__':
t1 = TestAttribute()
t2 = TestAttribute()
t1.addContent('t1')
TestAttribute.content.append('tt')
print 'object t1:', t1.content ,t1.__dict__
print 'object t2:', t2.content ,t2.__dict__
print 'class TestAttribute:', TestAttribute.content1
2
3object t1: ['t1'] {'content':['t1']}
object t2: [] {'content':[]}
class TestAttribute: ['tt']
那么如何为一个实例添加属性呢?
答案是通过赋值号 = 给实例所需添加的属性赋值。 通过赋值号 = 给实例所需添加的属性赋值实际上是将这个属性指向了新的引用,也就是新的内存空间。
如在例一中没有通过赋值号为 content 赋值,所以这个属性并没有成为 t1 自己的属性,输出t1.__dict__ 为空。而在例二中的构造函数里面为每个实例的content均赋值,所以例二中的三个对象的content属性独立。通过下面的例子可以更深入说明这点:
1 | class TestAttribute: |
输出结果: 1
2object t1: 1 {'num': 1}
object t2: 0 {}
最后,小结如下: 1.Python中的类和实例是两个完全独立的对象; 2.Python中属性的获取是按照从下到上的顺序来查找属性; 3.为实例添加属性的方法:通过赋值号 = 给实例所需添加的属性赋值