浅谈python中的继承

it2025-03-03  21

python中的继承

继承的意义在于可以复用前面一个类的方法和属性,避免了代码重复,提高开发效率,作为一个程序员简洁应该是每个程序员应该追求的,那么继承就可以帮我们很好的做到这一点

接下来我们来看一个不使用继承的例子:

class Parent: def __init__(self, name): self.name = name def eat(self, foot): return '{} is eating {}'.format(self.name, foot) class Children: def __init__(self, name): self.name = name def eat(self, foot): return '{} is eating {}'.format(self.name, foot) c = Children('Amy') print(c.name) # Amy print(c.eat('rice')) # Amy is eating rice p = Parent('Amy') print(p.name) # Amy print(p.eat('rice')) # Amy is eating rice

看完这个例子肯定有人要问,这两个类的内容不是一毛一样的吗,这样写着多麻烦啊,如果还有几个一样的方法是不是还要加几个一样的,所以说当然不喽,接下来继承就派上用场了

单继承

class Parent: def __init__(self, name): self.name = name def eat(self, foot): return '{} is eating {}'.format(self.name, foot) class Children(Parent): pass c = Children('Amy') print(c.name) # Amy print(c.eat('rice')) # Amy is eating rice p = Parent('Amy') print(p.name) # Amy print(p.eat('rice')) # Amy is eating rice

从上面的例子发现当使用继承后class Children(Parent),那么好像被继承类的属性和方法都被继承类使用了,其实也确实如此

多继承

class Animal: def __init__(self, name): self.name = name def eat(self, foot): return '{} is eating {}'.format(self.name, foot) class Fish: def eat(self, foot): return 'This is {}'.format(foot) class Shark(Fish, Animal): pass s = Shark('kitty') print(s.name) # kitty print(s.eat('rice')) # This is rice

注意看一下,我们的Shark类继承了两个类,Animal类定义了name属性,但是Fish类并没有定义name属性,再看一下执行结果,我们发现,s.name执行结果是kitty,也就是说继承了Animal类,但是s.eat(rice)却执行了This is rice,也就是说它只继承了Fish类,所以结论是:当处于多继承时采用就近原则,如果就近没有再执行后面的,这是通俗理解,其实本质是调用了以下的方法,并按打印结果由左至右顺序执行,如果找到最后一个类,还没有找到方法,程序报错

print(Shark.__mro__) # (<class '__main__.Shark'>, <class '__main__.Fish'>, <class '__main__.Animal'>, <class 'object'>)

但是问题又来了,上面的继承我们完全继承了,那我们想要继承但是又想要自己定义该怎么办呢,别急,下面就给介绍方法重写

方法重写

class Animal: def __init__(self, name): self.name = name def eat(self, foot): return '{} is eating {}'.format(self.name, foot) class Fish(Animal): def __init__(self, name, age): Animal.__init__(self, name) # self参数一定要加上 self.age = age f = Fish('Amy', 18) print(f.name) # Amy print(f.age) # 18

上面这种方法是使用类去继承父类,但是它是有弊端的,比如说如果父类变了,那么继承父类的方法都要修改,但是他的弊端还不仅如此,比如:

class Animal: def __init__(self, name): self.name = name class Fish: def __init__(self, age): self.age = age class Shark(Animal, Fish): def __init__(self, name, age): Animal.__init__(self, name) Fish.__init__(self, age) s = Shark('kitty', 18) print(s.name) # kitty print(s.age) # 18

从上面的代码发现问题又来了,如果是多继承呢,那么方法就需要写多个继承,那么再继承多点,岂不是还要多写几个,答案是的,但是有没有方法改善呢,答案还是有的,我们可以调用super()函数

class Animal: def __init__(self, name, *args): super().__init__(*args) self.name = name class Fish: def __init__(self, age, *args): super().__init__() self.age = age class Shark(Animal, Fish): def __init__(self, name, age): super().__init__(name, age) s = Shark('kitty', 18) print(s.name) # kitty print(s.age) # 18 print(Shark.__mro__) # (<class '__main__.Shark'>, <class '__main__.Animal'>, <class '__main__.Fish'>, <class '__main__.Biology'>, <class 'object'>)

super()调用过程:上面s初始化时,先执行Shark中__init__方法,其中的__init__有super()调用,每执行一次super()时,都会从__mro__方法元组中顺序查找搜索。所以先调用Fish的__init__方法,在Fish中又有super()调用,这个时候就就根据__mro__表去调用object中的__init__,然后调用Animal的__init__,在Animal中又有super()调用,这个就根据__mro__表又去调用object中的__init__.

优先级

class A: def f1(self): print("A") self.f2() class B(A): def f2(self): print("B") class C: def f2(self): print("C") class D(C,B): pass d1 = D() # self指向d1 d1.f1() # A,C

以上执行流程:D无找C,C无找B,B无找A,A有。A中调用f2()方法,同样从D开始,D无找C,C有结束,所以打印A C

最新回复(0)