浅谈python中的继承

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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值