字典的value为自定义类,静态方法与实例方法的区别及调用方式,self与__init__方法的作用
class Fun():
name = 'class_fun'
def __init__(self, speed):
self.speed = speed
@staticmethod
def display():
print('start')
car = {'brand': '奔驰','country': '德国', 'price': 3000, 'class': Fun}
这里首先定义一个Fun类,然后创建一个字典car,其中键为’class‘的一项的value为该类名。
这里的修饰说明这个方法是一个静态方法,不能访问实例属性。注意如果希望一个方法作为静态方法,那么该方法里的“self”得去掉。实例方法不需要任何修饰。
这里的name是一个类属性,类属性的特点是,它们是所有相同类型对象的共同属性,即所有对象共用一个属性;而实例属性是每一个对象的特征,每一个对象的实例属性可以不同。
这里的self.speed是实例属性。实例属性需要在初始化方法里面定义,即__init__里。
解释器在执行 像fun = Fun(300)
这样的 实例化类对象 的代码时,首先,解释器会 在内存中 创建一个该类 的 实例对象;然后,解释器会查看这个类是否有 __init__方法,如果有,就会去调用它。
init 是 创建好实例后 立即就要 执行 的方法,所以称之为初始化方法。
通常我们会在__init__方法里面 执行一些初始化的动作,主要就是创建该实例的 实例属性。
init 方法的第一个参数是 self, 它 是干什么用的呢?
刚才说了, 解释器执行实例化代码,会先在内存中创建该类实例对象,然后调用类 的__init__方法。
调用 __init__方法时,就将实例对象 传递给 self参数。self 参数 需要传入实例对象本身,解释器会自动帮我们传入,不需要我们手动传入。
self 参数变量 指向的 就是 实例对象 本身,所以,self.speed = speed
就是创建该实例的属性speed了。下面进行一些输出测试:
输入:
# 这里没有创建一个实例
print(car['class'].name)
# 这里首先创建一个实例,然后调用display静态方法
print(car['class'](100).display())
输出:
'class_fun'
start
对于静态方法,可以不用像上面那样先定义一个实例然后再调用,可以直接使用类名调用
输入:
print(car['class'].display())
输出:
start
如果将该静态方法改成实例方法,首先将方法括号里的self去掉,其实去掉之后上面的装饰器就起不到作用了,为了避免造成误解最好也把装饰器去掉,然后试试直接使用类名调用实例方法:
输入:
print(car['class'].display())
输出:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-9-524169c831e9> in <module>()
----> 1 car['class'].display()
TypeError: display() missing 1 required positional argument: 'self'
报错。想要调用实例方法,得先创建一个实例。
类的继承
继承类的时候首先要在子类中传入父类,然后再在子类的初始化方法里调用父类的初始化方法。
其中调用父类的初始化方法有三种常用的方式:
方式1:
class Fun():
name = 'class_fun'
def __init__(self, speed):
self.speed = speed
@staticmethod
def display():
print('start')
class FunSon(Fun):
def __init__(self, speed, color): # 先加上父类的形参然后加上子类自己的形参
super(FunSon, self).__init__(speed) # 将父类的形参重新写一遍
self.color = color
方式2:
class Fun():
name = 'class_fun'
def __init__(self, speed):
self.speed = speed
@staticmethod
def display():
print('start')
class FunSon(Fun):
def __init__(self, speed, color):# 先加上父类的形参然后加上子类自己的形参
Fun.__init__(self, speed) # 将父类的形参重新写一遍
self.color = color
方式3:
class Fun():
name = 'class_fun'
def __init__(self, speed):
self.speed = speed
@staticmethod
def display():
print('start')
class FunSon(Fun):
def __init__(self, speed, color):# 先加上父类的形参然后加上子类自己的形参
super().__init__(speed) # 将父类的形参重新写一遍
self.color = color
其中几种方式都要注意的是,在子类的初始化方法的后面参数列表里需要将父类的实例属性全部写进去,然后再加上子类自己独有的实例属性。
使用super的好处之一就是:子类中调用父类的方法,不需要 显式指定 父类的名字。 代码的可维护性更好。
想象一下,如果Fun有很多子类,如果Fun类改了名字,采用super这样的写法,就不需要修改子类的代码了。
注意 super不仅仅可以调用父类的初始化方法,也可以调用父类的其他方法。
要注意一种情况,如果参数已经有了默认值,不能在调用父类的初始化方法的时候还将默认值写上去,如:
class Father():
def __init__(self, img_rgb, metadata=None, scale=1.0, instance_mode=7):
self.img_rgb = img_rgb
self.metadata = metadata
self.scale = scale
self.instance_mode = instance_mode
class Son(Father):
def __init__(self, img_rgb, metadata=None, scale=1.0, instance_mode=7):
super().__init__(img_rgb, metadata=None, scale=1.0, instance_mode=7)
self.old = []
f = Son('img', 'metadata')
print(f.img_rgb, f.metadata, f.scale, f.instance_mode, f.old)
这样的输出如下:
img None 1.0 7
你会发现不论赋什么值,最后的输出metadata和scale以及instance_mode始终是默认值,这是因为在子类中调用父类的初始化方法的时候出了问题,应该改为:
class Father():
def __init__(self, img_rgb, metadata=None, scale=1.0, instance_mode=7):
self.img_rgb = img_rgb
self.metadata = metadata
self.scale = scale
self.instance_mode = instance_mode
class Son(Father):
def __init__(self, img_rgb, metadata=None, scale=1.0, instance_mode=7):
super().__init__(img_rgb, metadata, scale, instance_mode)
self.old = []
f = Son('img', 'metadata')
print(f.img_rgb, f.metadata, f.scale, f.instance_mode, f.old)
最后的输出为:
img metadata 1.0 7 []
当然,如果子类 没有 自己的初始化方法,实例化子类对象时,解释器会自动调用父类初始化方法,比如下面的情况:
class Fun():
name = 'class_fun'
def __init__(self, speed):
self.speed = speed
@staticmethod
def display():
print('start')
class FunSon(Fun):
pass
类中的__repr__方法
car = FunSon(100,'red')
print(car)
输出:
<__main__.FunSon object at 0x7fb622f98860>
输出的是实例对象car储存的位置。但是如果希望输出一些car的基本信息呢?需要定义__repr__方法:
def __repr__(self):
return f'speed = {self.speed}, color = {self.color}'
print(car)
speed = 100, color = red