谨慎修改Python的类属性
- Python的类和类实例都是可变对象,可以随时给属性赋值,并且在原处修改。
- 在对类属性进行修改时需要特别小心,因为所有的类实例都继承共享类属性,除非实例本身存在和类属性同名的属性。对类属性进行修改,会影响到所有由这个类生成的实例。
- 在编写程序的时候,千万不要对实例属性和类属性使用相同的名字,因为相同名称的实例属性将屏蔽掉类属性,但是当你删除实例属性后,再使用相同的名称,访问到的将是类属性。
下边是一个测试的例子
1 #-*- coding:utf8 -*-
2
3 class B:
4 testlist = [111,222]
5
6 if __name__ == "__main__":
7
8 b1=B()
9 b2=B()
10 # 打印实例testlist的参数
11 print("-----step 1-----")
12 print("class B.testlist: ",B.testlist ,id(B.testlist) )
13 print("instance b1.testlist:",b1.testlist ,id(b1.testlist))
14 print("instance b2.testlist:",b2.testlist ,id(b2.testlist))
15 #修改类的属性
16 B.testlist.append(123)
17 # 类的属性被修改,实例的属性也会变化
18 print("-----step 2-----")
19 print("class B.testlist: ",B.testlist ,id(B.testlist) )
20 print("instance b1.testlist:",b1.testlist ,id(b1.testlist))
21 print("instance b2.testlist:",b2.testlist ,id(b2.testlist))
22
23 # 通过实例修改的类变量,其他实列的类变量值也会发生变化
24 b1.testlist.append("b1")
25 print("-----step 3-----")
26 print("class B.testlist: ",B.testlist ,id(B.testlist) )
27 print("instance b1.testlist:",b1.testlist,id(b1.testlist))
28 print("instance b2.testlist:",b2.testlist,id(b2.testlist))
29
30 # 当对实例的属性重新赋值,则此实例的属性变化不会在影响类和其他实例
31 b1.testlist=["b1"]
32 b1.testlist.append("b1")
33 print("-----step 4-----")
34 print("class B.testlist: ",B.testlist ,id(B.testlist) )
35 print("instance b1.testlist:",b1.testlist,id(b1.testlist))
36 print("instance b2.testlist:",b2.testlist,id(b2.testlist))
37
38 # 当对类的属性重新赋值,实例的属性会同时发生变化,除非载此之前实例的属性已经被重新赋值
39 B.testlist=["B"]
40 B.testlist.append("B")
41 print("-----step 5-----")
42 print("class B.testlist: ",B.testlist ,id(B.testlist) )
43 print("instance b1.testlist:",b1.testlist,id(b1.testlist))
44 print("instance b2.testlist:",b2.testlist,id(b2.testlist))
45
46 # 让我们删除b1的实例属性试一下,b1的实例属性有何类属性保持一致了
47 del b1.testlist
48 print("-----step 6-----")
49 print("class B.testlist: ",B.testlist ,id(B.testlist) )
50 print("instance b1.testlist:",b1.testlist,id(b1.testlist))
51 print("instance b2.testlist:",b2.testlist,id(b2.testlist))
52
53 # 当删除类属性后,类属性和实例的属性都被删除,除非实例的属性被提前赋值
54 b1.testlist=['new b1']
55 del B.testlist
56 print("-----step 7-----")
57 try:
58 print("class B.testlist: ",B.testlist ,id(B.testlist) )
59 except Exception as e:
60 print(e)
61 try:
62 print("instance b1.testlist:",b1.testlist,id(b1.testlist))
63 except Exception as e:
64 print(e)
65 try:
66 print("instance b2.testlist:",b2.testlist,id(b2.testlist))
67 except Exception as e:
68 print(e)
69
70 # 如果实例没有对该属性重新赋值,则对此实例属性的删除将会失败
71 print("-----step 8-----")
72 B.testlist=["new B"]
73 try:
74 del b2.testlist
75 print("del")
76 except Exception as e:
77 print("del failed")
78 print(e)
79 try:
80 print("class B.testlist: ",B.testlist ,id(B.testlist) )
81 except Exception as e:
82 print(e)
83 try:
84 print("instance b1.testlist:",b1.testlist,id(b1.testlist))
85 except Exception as e:
86 print(e)
87 try:
88 print("instance b2.testlist:",b2.testlist,id(b2.testlist))
89 except Exception as e:
90 print(e)
91
92 """
93 -----step 1-----
94 ('class B.testlist: ', [111, 222], 58725704L)
95 ('instance b1.testlist:', [111, 222], 58725704L)
96 ('instance b2.testlist:', [111, 222], 58725704L)
97 -----step 2-----
98 ('class B.testlist: ', [111, 222, 123], 58725704L)
99 ('instance b1.testlist:', [111, 222, 123], 58725704L)
100 ('instance b2.testlist:', [111, 222, 123], 58725704L)
101 -----step 3-----
102 ('class B.testlist: ', [111, 222, 123, 'b1'], 58725704L)
103 ('instance b1.testlist:', [111, 222, 123, 'b1'], 58725704L)
104 ('instance b2.testlist:', [111, 222, 123, 'b1'], 58725704L)
105 -----step 4-----
106 ('class B.testlist: ', [111, 222, 123, 'b1'], 58725704L)
107 ('instance b1.testlist:', ['b1', 'b1'], 58768712L)
108 ('instance b2.testlist:', [111, 222, 123, 'b1'], 58725704L)
109 -----step 5-----
110 ('class B.testlist: ', ['B', 'B'], 58769288L)
111 ('instance b1.testlist:', ['b1', 'b1'], 58768712L)
112 ('instance b2.testlist:', ['B', 'B'], 58769288L)
113 -----step 6-----
114 ('class B.testlist: ', ['B', 'B'], 58769288L)
115 ('instance b1.testlist:', ['B', 'B'], 58769288L)
116 ('instance b2.testlist:', ['B', 'B'], 58769288L)
117 -----step 7-----
118 class B has no attribute 'testlist'
119 ('instance b1.testlist:', ['new b1'], 58768712L)
120 B instance has no attribute 'testlist'
121 -----step 8-----
122 del failed
123 B instance has no attribute 'testlist'
124 ('class B.testlist: ', ['new B'], 58769288L)
125 ('instance b1.testlist:', ['new b1'], 58768712L)
126 ('instance b2.testlist:', ['new B'], 58769288L)
127 """