Python进阶-09-多态性

来源:《Python从小白到大牛》关东升

多态性

在面向对象程序设计时,多态是一个非常重要的特性,理解多态有利于进行面向对象的分析与设计。

1.多态概念

发生多态要有两个前提条件:第一、继承——多态发生一定是子类和父类之间;第二、重写——子类重写了父类的方法。父类Figure(几何图形)有一个draw(绘图)函数,Figure(几何图形)函数有两个子类Ellipse(椭圆形)和Triangle(三角形),Ellipse和Triangle重写draw()方法。Ellipse和Triangle都有draw()方法,但具体实现的方式不同

    # 几何图形
    class Figure:
        def draw(self):
            print('绘制Figure...')

    # 椭圆形
    class Ellipse(Figure):
        def draw(self):
            print('绘制Ellipse...')

    # 三角形
    class Triangle(Figure):
        def draw(self):
            print('绘制Triangle...')

    f1=Figure()
    f1.draw         # 绘制Figure...  不符合,没有发生多态

    f2=Ellipse()
    f2.draw()       # 绘制Ellipse... 符合多态的两个前提

    f3=Triangle()
    f3.draw()       # 绘制Triangle... 符合多态的两个前提

多态发生时,Python解释器根据引用指向的实例调用它的方法。

    提示:与Java等静态语言相比,多态性对于动态语言Python而言意义不大。多态性优势在于运行期动态特征。

例如在Java中多态是指,编译期声明变量是父类的类型,在运行期确定变量所引用的实例。而Python不需要声明变量的类型,没有编译,直接由解释器运行,运行期确定变量所引用的实例。

2.类型检查

无论多态性对Python影响多大,Python作为面向对象的语言多态性是存在的,这一点可以通过运行期类型检查证实,运行期类型检查使用isinstance(object,classinfo)函数,它可以检查object实例是否由classinfo类或classinfo子类所创建的实例。

    # 几何图形
    class Figure:
        def draw(self):
            print('绘制Figure...')

    # 椭圆形
    class Ellipse(Figure):
        def draw(self):
            print('绘制Ellipse...')

    # 三角形
    class Triangle(Figure):
        def draw(self):
            print('绘制Triangle...')

    f1=Figure()
    f1.draw         # 绘制Figure...  不符合,没有发生多态

    f2=Ellipse()
    f2.draw()       # 绘制Ellipse... 符合多态的两个前提

    f3=Triangle()
    f3.draw()       # 绘制Triangle... 符合多态的两个前提

    print(isinstance(f1,Triangle))       # False
    print(isinstance(f2,Triangle))       # False
    print(isinstance(f3,Triangle))       # True
    print(isinstance(f2,Figure))         # True

isinstance(f2,Figure)表达式是True,f2是Ellipse类创建的实例,Ellipse是Figure类的子类,所以这个表达式返回True,通过这样的表达式可以判断是否发生了多态。另外,还有一个类似于isinstance(object,classinfo)的
issubclass(class,classinfo)函数,issubclass(class,classinfo)函数用来检查class是否是classinfo的子类。

    print(issubclass(Ellipse,Triangle))   # False
    print(issubclass(Ellipse,Figure))     # True
    print(issubclass(Triangle,Ellipse))   # False

3.鸭子类型

多态性对于动态语言意义不是很大,在动态语言中有一种类似检查称为“鸭子类型”即一只鸟走起来像鸭子、游起来像鸭子、叫起来也像鸭子,那它就可以被当作鸭子。鸭子类型不关注变量的类型,而是关注变量具有的方法。鸭子类型像多态一样工作,但是没有继承,只要像“鸭子”一样的行为(方法)就可以了。
鸭子类型示例代码如下:

    class Animal(object):
        def run(self):
            print('动物跑...')

    class Dog(Animal):
        def run(self):
            print('狗狗跑...')

    class Car:
        def run(self):
            print('汽车跑...')

    def go(Animal):    # 接收参数是Animal
        animal.run()

    go(Animal)          # 动物跑...
    go(Dog)             # 狗狗跑...
    go(Car)             # 汽车跑...

上述代码定义了三个类Animal、Dog和Car,从代码可以看出Dog继承了Animal,而Car与Animal和Dog没有任何的关系,只是他们都有run()方法。上述代码定义了go()函数,设计时考虑接受Animal类型参数,但是由于Python解释器不做任何的类型检查,所以可以传入任何的实际参数。当在go()函数传入Car实例时,它可以正常执行,这就是鸭子类型。
在Python这样的动态语言中使用“鸭子类型”替代多态性设计,能够充分地发挥Python动态语言特点,但是也给软件设计者带来了困难,对程序员的要求也非常高。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值