学习python的面向对象时,我发现,与普通函数不同,类中的每个函数(属性或者方法)中的第一个参数都是self,那么如何理解python类中的self呢?
self代表类的实例化
首先我们明确python中的self只在类中存在,代表class的实例化,即self = 类的实例。这里举个栗子:
class Car:
#init method or constructor
def __init__(self, model, color):
self.model = model
self.color = color
def show(self):
print("Model is", self.model)
print("Color is", self.color)
audi = Car("audi a4", "blue")
ferrari = Car("ferrari 430", "red")
audi.show() # same output as Car.show(audi)
Car.show(audi)
ferrari.show() # same output as Car.show(ferrari)
Car.show(ferrari)
Output:
Model is audi a4
Color is blue
Model is audi a4
Color is blue
Model is ferrari 430
Color is red
Model is ferrari 430
Color is red
通过audi.show()与Car.show(audi)的输出结果相同,我们可以看出self代表类的实例,在这个栗子中,self.model和self.color声明的是类的实例中的变量,对于audi和ferrari两个不同的对象,值是不同的。当然我们也可以不使用self进行声明,那么此时的变量为类变量,即在所有的车(对象)都会有相同的model和color。
python中self并不是一个关键词,可以用其他词替换
不同于C++中的this,python中的self并不是一个关键词,这就意味着你可以将其替换为其它任何词,this,that or anything you like。但是约定俗成,我们最好还是使用self。
什么时候使用self?
前面提到self代表类的实例,但是实际使用时仍然会让人费解。简单地说,self可以看成是全局变量,如果变量前加了self,那么任意实例(对象)的方法就都可以访问这个变量;如果没有加self,只有在当前函数内部才能访问这个变量。
所有加了self的变量,需要确保在构造函数init中出现,否则该变量也不是成员变量。具体可参考如下代码。
class TestVar:
var1 = 100
def __init__(self):
self.var2 = 200
def testVariable(self,var =400):
var3 = 300
self.var4 = var
self.var5 = 500
tmp = TestVar()
print(TestVar.var1)
print(tmp.var1)
print(TestVar.var2)
print(tmp.var2)
print(tmp.var3)
print(tmp.var4)
print(tmp.var5)
Output:
100
100
AttributeError: type object 'TestVar' has no attribute 'var2'
200
AttributeError: 'TestVar' object has no attribute 'var3'
AttributeError: 'TestVar' object has no attribute 'var4'
AttributeError: 'TestVar' object has no attribute 'var5'
在这段程序中,var1是类变量,可以由类名直接调用,也可以通过实例化的对象来进行调用;var2是成员变量,可以通过对象调用,但是不能通过类本身进行调用;
var3为函数内部变量,即局部变量;var4和var5前面虽然加了self,但是未在构造函数init进行初始化,所以不是成员变量。
python中的类变量和C++中的静态变量不同
接上段代码,#后为输出结果。
tmp2 = TestVar()
tmp.var1 = 200
print(tmp2.var1) # 100
print(TestVar.var1) # 100
TestVar.var1 = 1000
print(tmp.var1) # 200
print(tmp2.var1) # 1000
对象的内存中包含了成员变量(例如,self.xx),不同的对象占用不同的内存,这使得不同对象的成员变量相互独立,它们的值不受其他对象的影响对于成员变量。C++的类中的静态变量只被分配了一份内存,所有对象都是使用该内存中的数据,因此任意对象修改了该变量,都会影响到其他变量。而python中的类变量则不同,它并不是由类的所有对象共享,因此tmp修改了var1的值,并不影响其他对象(tmp2)以及类本身;只有类本身才能修改类变量的值,当一个对象被构造时(tmp2),则将当前类变量的值拷贝给该对象。
Reference