self代表的是类的实例,而不是类
class Test(object):
def prt(self):
print(self)
print(self.__class__)
t = Test()
t.prt()
执行结果:
<__main__.Test object at 0x10fe90fd0>
<class '__main__.Test'>
从上面的执行结果可以看出,self指向是类的实例对象,self.__class__指向的类
self是必写的?
在Python解释器内部,当我们调用t.prt()时,实际上解释器解释为Test.prt(t),也就是说把self替换成类的实例
class Test(object):
def prt(self):
print(self)
print(self.__class__)
t = Test()
# t.prt()
Test.prt(t)
代码与上面代码运行结果一样。
实际上self是不可以省略的
class Test(object):
def prt():
# print(self)
# print(self.__class__)
print('aaa')
t = Test()
t.prt()
运行结果:
TypeError: prt() takes 0 positional arguments but 1 was given
prt()方法在定义时没有定义参数,但是我们运行时强行传了一个参数,等同于我们传了一个参数t。
如果我们定义和调用时均不传类实例是可以的,这就是类方法:
class Test(object):
def prt():
# print(self)
# print(self.__class__)
print('aaa')
t = Test()
# t.prt()
Test.prt()
运行结果为:aaa
在继承时,传入的是哪个实例,就是那个传入的实例,而不是定义了self类的实例
class Parent:
def p(self):
print(self)
class Child(Parent):
def c(self):
print(self)
cl = Child()
cl.c()
cl.p()
pa = Parent()
pa.p()
运行结果:
<__main__.Child object at 0x107cf4e90>
<__main__.Child object at 0x107cf4e90>
<__main__.Parent object at 0x107cf4e10>
运行cl.p()时,相当于Child.p(cl),所以self指的是Child类的实例,由于Child中没有定义p(),所以会沿着继承树往上找,在Parent类中有p()方法,所以就会成功调用
在描述符类中,self指的是描述符类的实例
class Desc:
def __get__(self, ins, cls):
print('self in Desc: %s ' % self )
print(self, ins, cls)
class Test:
x = Desc()
def prt(self):
print('self in Test: %s' % self)
t = Test()
t.prt()
t.x
运行结果:
self in Test: <__main__.Test object at 0x105c26dd0>
self in Desc: <__main__.Desc object at 0x105c26d10>
<__main__.Desc object at 0x105c26d10> <__main__.Test object at 0x105c26dd0> <class '__main__.Test'>
此处调用的是t.x,也就是说是Test类的实例t的属性x,由于实例t中并没有定义属性x,所以找到了类属性x,而该属性是描述符属性,为Desc类的实例而已,所以此处并没有顶用Test的任何方法。
那么我们如果直接通过类来调用属性x也可以得到相同的结果。
下面是把t.x改为Test.x运行的结果。
self in Test: <__main__.Test object at 0x10334cdd0>
self in Desc: <__main__.Desc object at 0x10334cd10>
<__main__.Desc object at 0x10334cd10> None <class '__main__.Test'>