零基础入门学习Python(36) 类和对象:继承

继承的语法结构

class DervieClassName(BaseClassName)

  • 被继承的类我们称之为“父类”,“基类”或“超类”,而继承者我们称之为“子类”
  • 子类可以继承父类的任何属性或方法
在这里插入代码片>>> class Parent:
	def hello(self):
		print('正在调用父类的方法 ')

		
>>> class Child(Parent):#括号里面填写的是父类
	pass

>>> p = Parent()#给父类实例化
>>> p.hello()
正在调用父类的方法 
>>> c = Child()#给子类实例化
>>> c.hello()
正在调用父类的方法 

在这里插入图片描述
注意:如果子类中定义与父类同名的方法或属性,则会自动覆盖父类对应的方法或属性
在这里插入图片描述

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 Crap(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()
>>> fish.move()
我的位置是: 8 10
>>> fish.move()
我的位置是: 7 10
>>> goldfish = Goldfish()
>>> goldfish.move()
我的位置是: 1 0
>>> goldfish.move()
我的位置是: 0 0
>>> shark = Shark()
>>> shark.eat()
吃货的梦想就是天天有的吃
>>> shark.eat()
太撑了,吃不下了
>>> shark.move()
Traceback (most recent call last):
  File "<pyshell#30>", line 1, in <module>
    shark.move()
  File "D:/我的python学习/python36-fish.py", line 8, in move
    self.x -= 1
AttributeError: 'Shark' object has no attribute 'x'

在这里插入图片描述

子类重写覆盖了父类的解决方法

1.调用未绑定的父类方法

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 Crap(Fish):
    pass

class Salmon(Fish):
    pass

class Shark(Fish):
    def __init__(self):
        Fish.__init__(self)#调用父类的方法,
        #这里的self并不是父类的实例对象,他是子类shark的实例对象,这里Shark实例化后把self传进来
        #所以说这里是未绑定的父类方法,没有绑定父类给的是子类的实例对象
        #相当于Fish.__init__(shark)
        self.hungry = True
    def eat(self):
        if self.hungry:
            print('吃货的梦想就是天天有的吃')
            self.hungry = False
        else:
            print('太撑了,吃不下了')
            
>>> shark = Shark()
>>> shark.move()
我的位置是: 5 9
>>> shark.move()
我的位置是: 4 9
>>> Fish.__init__(shark)
>>> shark.move()
我的位置是: 7 6

2.使用super函数

  • 使用super函数可以帮助我们自动找到基类的方法,而且还可以为我们传入self参数
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 Crap(Fish):
    pass

class Salmon(Fish):
    pass

class Shark(Fish):
    def __init__(self):
        super().__init__()#super函数不用给定任何基类的名字,会自动一层层找出所有基类里面对应的方法,由于不用给出基类的名字,意味着如果想要改变类的继承关系只需要修改括号里的类名即可
        self.hungry = True
    def eat(self):
        if self.hungry:
            print('吃货的梦想就是天天有的吃')
            self.hungry = False
        else:
            print('太撑了,吃不下了')

多重继承

  • 可以同时继承多个父类的属性和方法
  • class DeriveClassName(Base1,Base2,Base3):

>>> class Base1:
	def foo1(self):
		print('我是foo1,我为Base1代言')

>>> class Base2:
	def foo2(self):
		print('我是foo2,我为Base2代言')

		
>>> class C(Base1,Base2):
	pass

>>> c = C()
>>> c.foo1()
我是foo1,我为Base1代言
>>> c.foo2()
我是foo2,我为Base2代言
  • 多重继承很容易导致代码混乱,当不确定真的要使用多重继承时,请尽量避免使用它,否则很可能出现不可预见的bug

Task

0. 继承机制给程序猿带来最明显的好处是?
如果一个类 A 继承自另一个类 B,就把这个 A 称为 B 的子类,把 B 称为 A 的父类、基类或超类。继承可以使得子类具有父类的各种属性和方法,而不需要再次编写相同的代码(偷懒)。
在子类继承父类的同时,可以重新定义某些属性,并重写某些方法,即覆盖父类的原有属性和方法,使其获得与父类不同的功能。另外,为子类追加新的属性和方法也是常见的做法。
1. 如果按以下方式重写魔法方法 init,结果会怎样?
会报错,因为 init 特殊方法不应当返回除了 None 以外的任何对象。

class MyClass:
        def __init__(self):
                return "I love FishC.com!"

>>> myClass = MyClass()
Traceback (most recent call last):
  File "<pyshell#13>", line 1, in <module>
    myClass = MyClass()
TypeError: __init__() should return None, not 'str'

2. 当子类定义了与相同名字的属性或方法时,Python 是否会自动删除父类的相关属性或方法?
不会删除,会覆盖
3. 假设已经有鸟类的定义,现在我要定义企鹅类继承于鸟类,但我们都知道企鹅是不会飞的,我们应该如何屏蔽父类(鸟类)中飞的方法?
覆盖父类。
4. super 函数有什么“超级”的地方?
super 函数超级之处在于你不需要明确给出任何基类的名字,它会自动帮您找出所有基类以及对应的方法。由于你不用给出基类的名字,这就意味着你如果需要改变了类继承关系,你只要改变 class 语句里的父类即可,而不必在大量代码中去修改所有被继承的方法。
5. 多重继承使用不当会导致重复调用(也叫钻石继承、菱形继承)的问题,请分析以下代码在实际编程中有可能导致什么问题?

class A():
    def __init__(self):
        print("进入A…")
        print("离开A…")

class B(A):
    def __init__(self):
        print("进入B…")
        A.__init__(self)
        print("离开B…")
        
class C(A):
    def __init__(self):
        print("进入C…")
        A.__init__(self)
        print("离开C…")

class D(B, C):
    def __init__(self):
        print("进入D…")
        B.__init__(self)
        C.__init__(self)
        print("离开D…")

多重继承容易导致重复调用问题,下边实例化 D 类后我们发现 A 被前后进入了两次

>>> d = D()
进入D…
进入B…
进入A…
离开A…
离开B…
进入C…
进入A…
离开A…
离开C…
离开D…

6. 如何解决上一题中出现的问题?
用super()函数

class A():
    def __init__(self):
        print('进入A...')
        print('离开A...')
class B(A):
    def __init__(self):
        print('进入B...')
        super().__init__()
        print('离开B...')

class C(A):
    def __init__(self):
        print('进入C...')
        super().__init__()
        print('离开C...')

class D(B,C):
    def __init__(self):
        print('进入D...')
        super().__init__()
        print('离开D...')

7. 定义一个点(Point)类和直线(Line)类,使用 getLen 方法可以获得直线的长度。)
提示:
设点 A(X1,Y1)、点 B(X2,Y2),则两点构成的直线长度 |AB| = √((x1-x2)2+(y1-y2)2)
Python 中计算开根号可使用 math 模块中的 sqrt 函数
直线需有两点构成,因此初始化时需有两个点(Point)对象作为参数

import math

class Point():
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    def getX(self):
        return self.x

    def getY(self):
        return self.y

class Line():
    def __init__(self, p1, p2):
        self.x = p1.getX() - p2.getX()
        self.y = p1.getY() - p2.getY()
        self.len = math.sqrt(self.x*self.x + self.y*self.y)

    def getLen(self):
        return self.len

>>> p1 = Point(1, 1)
>>> p2 = Point(4, 5)
>>> line = Line(p1, p2)
>>> line.getLen()
5.0

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值