首先要理解的是“实例变量”。
我们在__init__方法中并不是创建了实例变量,我们是添加了一个或者多个属性给实际的对象
在__init__内部 self.x = 5和外部 f.x = 5没有什么不同。
那么类呢?
1 >>> class Bar(object): 2 pass 3 4 >>> Bar.foo = 100 5 >>> Bar.foo 6 100 7 >>> Bar 8 <class '__main__.Bar'>
类也是对象,所以它也有属性。但是有一个疑问。我们可以为每一个实例对象定义一个属性通过__init__方法。
那创建一个类的属性,是怎么样的?
答案很简单。函数内部的代码块和类的代码块。函数的内部代码只有当函数触发是才会执行,类的代码块是在类定义好后就执行的,只执行一次
1 >>> class Foo(): 2 print("hello") 3 4 5 hello 6 >>>
1 >>> class Foo(): 2 x = 100 3 4 5 >>> Foo.x 6 100
如果我们定义了一个函数,我只是在当前作用域创建了一个变量,如果在类里面定义一个方法,其实是创建了一个新的属性
1 >>> class Foo(): 2 def blah(self): 3 return "blash" 4 5 6 >>> Foo.blah 7 <unbound method Foo.blash>
换句话说,实例的方法在类里面,不在实例对象上,当我们触发f.blah()时,相当于这样f.blah()和Foo.blah(f)
如果我触发f.blah(),python怎么知道去触发Foo.blah? f和Foo是完全两个不同的对象。f是Foo的实例对象,Foo是type的实例对象,python是如何找到Foo的blah属性的呢?
python有不同的规则用于变量和属性区域,对于变量,python遵守LEGB规则:本地,闭合,全局,内建。
对于属性,首先它会在对象上寻找,然后再去寻找这个对象的类,然后去寻找这个类的父类。知道寻找到object类
因此f.blah(),先找实例对象f,没有找到属性名blah,去找这个类Foo,在这里找到了然后通过一些方法执行Foo.blah(f)
所以python没有实际上的类变量和实例变量之分。有的只是对象的属性。一些事定义在类本身上。一些是建立在类的实例对象上。(当然,类也是type的实例对象,现在往我们忘记它)。这也是为什么一些人认为他们应该定义类上的属性(类变量)。因为它们对实例对象时可见的。
最后来看一下代码
1 >>> class Person(): 2 population = 0 3 def __init__(self, f, s): 4 self.f = f 5 self.s = s 6 self.population +=1 7 8 9 >>> p1 = Person('s','ss') 10 >>> p2 = Person('a', 'aa') 11 >>> p1.population 12 1 13 >>> p1.population 14 1 15 >>> p2.population 16 1 17 >>> Person.population 18 0