自学的小记录,大佬绕道
1、一个子类可以继承它的父类的所有属性和方法
先看一个具体的例子
# 继承
class Parent:
def hello(self):
print('调用父类的hello方法')
# class DerivedClassName(BaseClassName):
class Child(Parent):
pass # 直接向下执行
p = Parent()
c = Child()
p.hello()
# c.hello()
我们发现直接调用c.hello也能执行父类中的方法,这说明一个子类可以继承它的父类的所有属性和方法
2、如果子类中定义与父类同名的方法或属性,则会自动覆盖父类对应的方法和属性(即子类方法属性改变,父类是不变的)
# 继承:一个子类可以继承它的父类的所有属性和方法
class Parent:
def hello(self):
print('调用父类的hello方法')
# 如果子类中定义与父类同名的方法或属性,则会自动覆盖父类对应的方法和属性(即子类方法属性改变,父类是不变的
class Child(Parent):
def hello(self):
print('调用子类的hello方法')
p = Parent()
c = Child()
p.hello()
c.hello()
运行结果
这里覆盖是子类实例对象里面的方法,父类是不受影响的
3、子类方法覆盖父类的解决方法
这里举一个简单的小例子,通过定义一个鱼的大类和不同种类的鱼,定义他们的移动、吃的方法。
import random as r
# 鱼的大类
class Fish:
def __init__(self):
self.x = r.randint(0, 10)
self.y = r.randint(0, 10)
def move(self):
self.x -= 1
print("目前的位置是", self.x, self.y)
# 金鱼
class Goldfish(Fish):
pass
# 鲤鱼
class Garp(Fish):
pass
# 三文鱼
class Salmon(Fish):
pass
# 鲨鱼
class Shark(Fish):
def __init__(self):
self.hungry = True
def eat(self):
if self.hungry:
print('继续吃')
self.hungry = False
else:
print('吃不下')
fish = Fish()
goldfish = Goldfish()
shark = Shark()
# 移动
fish.move()
goldfish.move() # 继承父类的方法
shark.eat() # 调用子类的方法
运行结果
可以看到,目前我们无论是调用父类的方法还是子类的方法,都能成功调用。
接下来我们调用
shark.move()
出现了报错
shark对象没有x这个属性
后来发现
class Shark(Fish):
# 这里重写了方法,会把父类当中的方法覆盖掉,导致无法获取x、y的属性
def __init__(self):
self.hungry = True
这里重写了方法,会把父类当中的方法覆盖掉,导致无法获取x、y的属性
为解决这个问题,有两种解决方法
(1)调用未绑定的父类方法
# 鲨鱼
class Shark(Fish):
# 这里重写了方法,会把父类当中的方法覆盖掉,导致无法获取x、y的属性
def __init__(self):
Fish.__init__(self) # 调用父类的方法,但是这里的self还是指向子类,相当于Fish.__init__(shark)
self.hungry = True
def eat(self):
if self.hungry:
print('继续吃')
self.hungry = False
else:
print('吃不下')
运行结果
没有报错
(2)使用super函数(super函数会帮我们自动找到基类的方法,而且还自动为我们传入self参数)
这个方法其实更便于理解和使用
# 鲨鱼
class Shark(Fish):
# 这里重写了方法,会把父类当中的方法覆盖掉,导致无法获取x、y的属性
def __init__(self):
super().__init__()
self.hungry = True
def eat(self):
if self.hungry:
print('继续吃')
self.hungry = False
else:
print('吃不下')
运行结果
同样也可以解决这个问题。super函数的方便之处就在于不用给定任何基类的名字,但是它会帮我们自动找到基类中对应的方法。(这里的一个好处就是如果我们采用第一种方法,当我们父类的名字改变时,我们需要改变子类中每一处使用init方法的地方:Fish.init(self),但是如果用super方法可以省去很多麻烦)
4、多重继承
下面用一个例子来具体说明
# 多重继承
class Base1:
def foo1(self):
print("Base1的foo1")
class Base2:
def foo2(self):
print("Base2的foo2")
# 多重继承
class C(Base1, Base2):
pass
c = C()
c.foo1()
c.foo2()
这里的c继承了Base1、Base2,可以继承他们的属性和方法,但是实际上多重继承很容易造成混乱,所以如果非必要不要使用多继承