先上一段代码
class Test():
x_num = 4
num = 1
y = 5
def __init__(self, num):
self.num = num
def change(self,num):
Test.num = num
Test.x_num = 21
def test(self):
self.x = 12
self.y = 15
a = Test(2)
print 'Test.num =', Test.num , '这里指定了是类的成员'
print 'Test.x_num =', Test.x_num , '这里指定了是类的成员'
print 'a.num =' , a.num , '对象中有num成员'
print 'a.x_num =', a.x_num , '对象中没有x_num成员,但是类成员中有x_num'
print 'a.y =', a.y
try:
print a.x
except:
print 'no attribute named x', '对象和类都没有x(这个时候test还没执行,所以对象里没有x),所以报错了'
a.test()
print 'test(),self.x = 12 -> a.x =', a.x, '非构造函数可以任意声明对象的成员'
print 'test(),self.y = 15 -> a.y =', a.y, '非构造函数可以任意声明对象的成员'
Test.x_num = 100
print 'Test.x_num=100 -> a.x_num =', a.x_num, '对于已创建的对象也会改'
a.change(6)
print 'a.change(6), Test.num=6 -> Test.num =', Test.num, '因为change中使用了Test.num,所以类中所有值都变了'
print 'a.change(6), Test.x_num=21 -> a.x_num =', a.x_num, '即使a已经创建了,改了Test.x_num, a的x_num是会变的'
a.x_num = 10
print 'a.x_num=10 -> Test.x_num =',Test.x_num, '这里是直接调用的,相当于只改了当前对象的类成员值,其他的类成员值不会改'
print 'a.x_num=10 -> Test().x_num = ', Test(123).x_num
通过上述例子能够得到:
对于对象引用的变量(line17、18)
- 如果init中有声明(line6),那么a.num是成员变量(line17)
- 如果init中没有这个声明(line18),类成员中有这个声明,则获取到类成员(line2、18,line4、19)
- 如果init中没有这个声明(line21),成员函数里有声明(line11),但是该成员函数还没有执行(line10、24),那么Python会提示实例中找不到属性(line20-23)
- 如果该成员函数已经执行,则会直接得到成员变量(line24、25),由于line24执行了test成员函数之后成员变量中已经有了y,所以在line26得到的成员函数,而不是line19中得到的类成员
对于类变量的引用(line2-4,8、9、15、16、27-34)
- 引用时需使用类名(line2、15,line3、16)
- 使用类名引用并更改类成员值后(line8、9、27、29),所有该类的对象引用该类成员时值都变为新的值(line28、30、31)
- 如果使用对象引用类成员并更改类成员值,不对其他类的对象或类成员直接引用造成影响(line32-34)
运行结果如下:
Test.num = 1 这里指定了是类的成员
Test.x_num = 4 这里指定了是类的成员
a.num = 2 对象中有num成员
a.x_num = 4 对象中没有x_num成员,但是类成员中有x_num
a.y = 5
no attribute named x 对象和类都没有x(这个时候test还没执行,所以对象里没有x),所以报错了
test(),self.x = 12 -> a.x = 12 非构造函数可以任意声明对象的成员
test(),self.y = 15 -> a.y = 15 非构造函数可以任意声明对象的成员
Test.x_num=100 -> a.x_num = 100 对于已创建的对象也会改
a.change(6), Test.num=6 -> Test.num = 6 因为change中使用了Test.num,所以类中所有值都变了
a.change(6), Test.x_num=21 -> a.x_num = 21 即使a已经创建了,改了Test.x_num, a的x_num是会变的
a.x_num=10 -> Test.x_num = 21 这里是直接调用的,相当于只改了当前对象的类成员值,其他的类成员值不会改
a.x_num=10 -> Test().x_num = 21