class my_class(): args1=1 def fun(self): print self.args1 my_c=my_class() my_c.fun()
请问在类里,那个self.args1 是类变量还是实例变量?类变量可以用self.args1用吗?
学习是最好的投资!
如果搞明白了 类空间和实例空间,这个问题就很简单了。类有自己的名字空间,可以通过className.__dict__查看得到里面的内容。 同样实例化一个实例的话, 那么这个实例也就有了自己的名字空间,用来存储实例的成员,方法等。当然一个实例肯定可以共享类的成员的。具体对你的case来说,如果print self.args1, 首先会在实例的名字空间内部查找, 没有发现args1这个成员,于是继续向上找到类的空间,发现有了args1,这样就会输出类的args1. 但是如果有赋值语句的话,比如self.args1 = 1, 那么实例就会在自己空间创建了args1这个成员。 看下面的代码:
className.__dict__
print self.args1
args1
self.args1 = 1
In [14]: class A(object): ....: args1 = 1 ....: def fun(self): ....: print self.args1 ....: def fun2(self): ....: self.args1 = 2 In [15]: a = A() In [16]: A.__dict__ # 这是类的名字空间,可以看到args1在里面 Out[16]: #删除了一些 { 'args1': 1, 'fun': <function __main__.fun>, 'fun2': <function __main__.fun2>} In [17]: a.__dict__ #而实例a的名字空间则没有args1 Out[17]: {} In [18]: a.fun() #执行func 则是查找到了类的args1的成员。 1 In [19]: a.fun2() #执行了func2, 这就会在a这个实例空间里面创建args1这个成员,与类的无关。 In [20]: a.__dict__ #可以看到a的空间里面已经 有了args1. Out[20]: {'args1': 2} In [21]: a.fun() #再次执行,则会直接输出实例a自己的args1. 2 In [22]: A.args1 #类与实例的空间互不影响。 Out[22]: 1 In [23]: b = A() #实例之间的空间也是相互独立, In [24]: b.args1 Out[24]: 1
结合上面的代码,应该可以从相对本质上理解了
类变量,这个可以通过直接打印类对象的id和用self限制的对象id是否相同来验证,类的地址和对象id是一样的,之所以可用self,是因为python默认先查找实例变量,找不到再找类变量,所以表面上看是对象变量,但实际上引用的是类变量。
class MyClass: args1 = 1 def fun(self): print id(self.args1) my_c = MyClass() print id(MyClass.args1) my_c.fun()
如果看的再深一点的话,实际上,这里的self只是表示绑定的对象,你讲其命名为其他的变量名也是可以的
class MyClass: args1 = 1 def fun(binding): #这里用的是binding,而不是self print id(binding.args1) my_c = MyClass() print id(MyClass.args1) my_c.fun()
class myclass(): args = 1 def fun(self): print self.args self.__class__.args += 1 if __name__ == '__main__': m1 = myclass() m1.fun() m2 = myclass() m2.fun()
结果为
1 2
明显是类变量
self.args1这是实例变量。my_class.args1这是类变量。
self.args1
my_class.args1
class my_class(): args1=1 def fun(self): print self.args1 #这是实例变量 print my_class.args1 #这是类变量
如果搞明白了 类空间和实例空间,这个问题就很简单了。类有自己的名字空间,可以通过
className.__dict__
查看得到里面的内容。 同样实例化一个实例的话, 那么这个实例也就有了自己的名字空间,用来存储实例的成员,方法等。当然一个实例肯定可以共享类的成员的。具体对你的case来说,如果
print self.args1
, 首先会在实例的名字空间内部查找, 没有发现args1
这个成员,于是继续向上找到类的空间,发现有了args1,这样就会输出类的args1. 但是如果有赋值语句的话,比如self.args1 = 1
, 那么实例就会在自己空间创建了args1这个成员。 看下面的代码:结合上面的代码,应该可以从相对本质上理解了
类变量,这个可以通过直接打印类对象的id和用self限制的对象id是否相同来验证,类的地址和对象id是一样的,之所以可用self,是因为python默认先查找实例变量,找不到再找类变量,所以表面上看是对象变量,但实际上引用的是类变量。
如果看的再深一点的话,实际上,这里的self只是表示绑定的对象,你讲其命名为其他的变量名也是可以的
结果为
明显是类变量
self.args1
这是实例变量。my_class.args1
这是类变量。self.args1这是实例变量。
my_class.args1这是类变量。