python入门

python第38课练习—类和对象:继承

2019-06-12  本文已影响0人  YoYoYoo

1、继承机制给程序员带来最明显的好处是?

答:可以偷懒,据说这是每一个优秀程序员的梦想!

2、如果按以下方式重写魔法方法 __init__,结果会怎样?

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

答:会报错,因为__init__特殊方法不应当返回除了None以外的任何对象。

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

3、当子类定义了与父类相同名字的属性或方法时,Python是否会自动删除父类的相关属性或方法?

答:不会删除!Python的做法跟其他大部分面向对象编程语言一样,都是将父类属性或方法覆盖,子类对象调用的时候会调用到覆盖后的新属性或方法,但父类的仍然还在,只是子类对象“看不到”。

4、假设已有鸟类的定义,现在我要定义企鹅类继承于鸟类,但我们都知道企鹅是不会飞的,我们应该如何屏蔽父类(鸟类)中飞的方法?

答:覆盖父类方法,例如将函数体内容写pass,这样调用fly方法就没有任何反应了。

class Bird:
    def fly(self):
        print('Fly away!')

class Penguin(Bird):
    def fly(self):
        pass

>>>bird = Bird()
>>>penguin = Penguin()
>>>bird.fly()
Fly away!
>>>penguin.fly()

5、super函数有什么“超级”的地方?

答:super函数超级之处在于你不需要明确给出任何基类(父类)的名字,它会自动帮你找出所有基类以及对应的方法。由于你不用给出基类的名字,这就意味着你如果需要改变类继承关系,你只要改变class语句里的父类即可,而不必在大量代码中去修改所有被继承的方法。
举个例子

    def __init__(self):
        Fish.__init__(self)
        self.hungry = True
    def __init__(self):
        super().__init__()  # 修改父类的时候这里就不用修改了
        self.hungry = True

6、多重继承使用不当会导致重复调用(也叫钻石继承、菱形继承)的问题,请分析以下代码在实际编程中有可能导致什么问题?

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被前后进入两次。
这有什么危害呢?举个例子,假设A的初始化方法里有一个计数器,那这样D一实例化,A的计数器就跑了两次(如果遭遇多个钻石重叠结构重叠还要更多),很明显是不符合程序设置的初衷的(程序应该可控,而不能受到继承关系影响)。

进入D...
进入B...
进入A...
离开A...
离开B...
进入C...
进入A...
离开A...
离开C...
离开D...

为了让大家明白,这里只是举例简单的钻石继承问题,在实际编程中,如果不注意多重继承的使用,会导致比这个复杂N倍的现象,调试起来不是一般的痛苦......所以要尽量避免多重继承。

7、如何解决上一题中出现的问题?

答: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...')

d = D()

输出:

进入D...
进入B...
进入C...
进入A...
离开A...
离开C...
离开B...
离开D...

练习

1、定义一个点(Point)类和直线(Line)类,使用getLen的方法可以获得直线的长度。

提示:

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)
print(line.getLen())

输出:

5.0
上一篇 下一篇

猜你喜欢

热点阅读