All C++ programmer know that there is a useful feature in C++ to share data in all instances of some class, which is called static member variable. Python also provides an intresting feature named class attribute, which can used to emulate this feature in C++.
Let's start our navigation from a simple example:
#! /usr/bin/python
class Counter:
count = 0
def Inc(self):
self.__class__.count += 1
print "There are %d instance" % (self.__class__.count)
if __name__ == "__main__":
x = Counter()
y = Counter()
print x.count, y.count
x.Inc()
print x.count, y.count
y.Inc()
print x.count, y.count
|
In above class, we can see that class Counter owns a unique member
variable "count" and a member function to increase the variable, x and y are instances of it. Because the member variable "count" is assigned at the class-level, it is called class attribue. To access the class attributes, python allows user to refer to it through either instances or the class. Let's look through the result of above program firstly:
0 0There are 1 instance1 1There are 2 instance2 2 We can see that the initial values of instance x and y are all 0, and after calling the member function Inc through instance x and y, the value shall be increased to 1 and 2, and the values of x and y should be kept same. It's worth noting that in function Inc, we use self.__class__.count rather than self.count to modify the value, which denotes that the modification should be executed on the class-level shared data.
Another intresting example is shown as below:
#! /usr/bin/python
class ShareData:
data = 1
if __name__ == "__main__":
x = ShareData()
y = ShareData()
print "data in x is %d" % (x.data)
print "data in y is %d" % (y.data)
print "data in ShareData is %d" % (ShareData.data)
ShareData.data = 10
print "data in x is %d" % (x.data)
print "data in y is %d" % (y.data)
print "data in ShareData is %d" % (ShareData.data)
x.data = 20
print "data in x is %d" % (x.data)
print "data in y is %d" % (y.data)
print "data in ShareData is %d" % (ShareData.data)
ShareData.data = 30
print "data in x is %d" % (x.data)
print "data in y is %d" % (y.data)
print "data in ShareData is %d" % (ShareData.data)
|
Class ShareData owns a unique class attribute data, and we will try to modify this variable through instance and class. Following is the result of above program:
data in x is 1data in y is 1data in ShareData is 1data in x is 10data in y is 10data in ShareData is 10data in x is 20data in y is 10data in ShareData is 10data in x is 20data in y is 30data in ShareData is 30The initial values of the three types of call are same, and after assigning the value 10 to ShareData.data, the value of x.data and y.data are all set to 10. But if we assign another value 20 to x.data, you can see the member variable data should not keep same value with ShareData.data any more.
This denotes that assignment to an instance's attribute will always change the object, and no other. This assignment will break the shared relation between the instances of a class.The third example maybe looks more intresting. We will replace the class attribute with a sequence type, such as a list, and you will learn more about the class attribute.
#! /usr/bin/python
class Server:
Observer = []
def Register(self, obs):
self.Observer.append(obs)
print "current oberservers contain %s" % (self.Observer)
if __name__ == "__main__":
x = Server()
y = Server() print "The shared oberservers contain %s" % (Server.Observer)
x.Register("x")
print "The shared oberservers contain %s" % (Server.Observer)
y.Register("y")
print "The shared oberservers contain %s" % (Server.Observer)
|
And the result of above program should be:
The shared oberservers contain []current oberservers contain ['x']The shared oberservers contain ['x']current oberservers contain ['x', 'y']The shared oberservers contain ['x', 'y']From the result, it seems that this example broke the rule summarized in the 2nd example. However, if you consider the case that a list is used as a parameter of a function, you can understand why the list will keep same in all instance. Just add following two statements into above codes:
z = Server()
z.Observer = []
And then you will still find the shared observers in the class still contains the string 'x' and 'y'.
阅读(838) | 评论(0) | 转发(0) |