python之abc模块

抽象类和接口:

java

我们先从java讲起,没有java基础的可以略过。

(挖坑) 

python

在python并没有抽象类之说,或者说抽象类=接口类(区别于接口)

继承有两种用途:

一:继承基类的方法,并且做出自己的改变或者扩展(代码重用)  

二:声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子类继承接口类,并且实现接口中的功能

在python中实现接口类必须借助于 abc模块

abc模块

前言:

面向对象的设计中,抽象类,接口这些必不可少的东西,在python中是如何提现的呢?

python作为一个动态语言,没有强类型的检查,而是以鸭子类型的方式提现,在执行的时候python不严格要求你必须是继承指定的父类而来,只要在调用的时候你有相应的方法和属性就可以了,长的像鸭子你就是鸭子。

也正是基于python这样的特性,python中没有interface的概念。

interface并不是普遍存在的,而是作为一个特例出现在java中,为的是解决多继承的问题。

python支持多继承,自然没有这个需要了。

然而我们难免会有这样的需求:子类必须实现某些指定的方法和属性,否则就抛异常。使用一些笨方法自然是可以达到相同的效果,但是python为我们提供了abc模块。

what is abc:

import abc
print([i for i in dir(abc) if not i.startswith("__")])
['ABC', 'ABCMeta', 'WeakSet', 'abstractclassmethod', 'abstractmethod', 'abstractproperty', 'abstractstaticmethod', 'get_cache_token']

How use abc?

竟然没报错?

from abc import ABCMeta, abstractmethod


class Drawable(metaclass=ABCMeta):

    # @abstractmethod
    def size(self):
        return 'Drawable size'

    # @abstractmethod
    def draw(self, x, y, scale=1.0):
        pass

    def double_draw(self, x, y):
        self.draw(x, y, scale=2.0)

d=Drawable()

说明。这个接口类竟然可以实例化。

接下来,我们给这个接口类添加一个abstractmethod方法的时候

class Drawable(metaclass=ABCMeta):

    @abstractmethod
    def size(self):
        return 'Drawable size'

    # @abstractmethod
    def draw(self, x, y, scale=1.0):
        pass

    def double_draw(self, x, y):
        self.draw(x, y, scale=2.0)

d=Drawable()

它报错了:TypeError: Can't instantiate abstract class Drawable with abstract methods size

总结:有抽象方法的接口类才是不能实例化。

接下来,我们继续看继承关系

from abc import ABCMeta, abstractmethod


class Drawable(metaclass=ABCMeta):

    # @abstractmethod
    def size(self):
        return 'Drawable size'

    # @abstractmethod
    def draw(self, x, y, scale=1.0):
        pass

    def double_draw(self, x, y):
        self.draw(x, y, scale=2.0)


class Cicle(Drawable):
    # def size(self):
    #     return 'Cicle size'

    # def draw(self, x, y, scale=1.0):
    #     print(x * scale, y * scale)
    def paint(self):
        pass


c=Cicle()

成功了。=》告诉我们继承一个没有抽象方法的接口类,并不用重写也能实例化。毕竟没有抽象方法。

那有抽象方法的接口类呢?

1.继承有抽象方法的接口类但没有重写抽象方法=》报错

from abc import ABCMeta, abstractmethod


class Drawable(metaclass=ABCMeta):

    @abstractmethod
    def size(self):
        return 'Drawable size'

    # @abstractmethod
    def draw(self, x, y, scale=1.0):
        pass

    def double_draw(self, x, y):
        self.draw(x, y, scale=2.0)


class Cicle(Drawable):=====》继承但没有实现抽象方法

    def paint(self):
        pass

c=Cicle()

TypeError: Can't instantiate abstract class Cicle with abstract methods size

2,继承有抽象方法的接口类必须重写抽线方法

from abc import ABCMeta, abstractmethod


class Drawable(metaclass=ABCMeta):

    @abstractmethod
    def size(self):
        return 'Drawable size'

    # @abstractmethod
    def draw(self, x, y, scale=1.0):
        pass

    def double_draw(self, x, y):
        self.draw(x, y, scale=2.0)


class Cicle(Drawable):
    def size(self):
        return 'Cicle size'

    def paint(self):
        pass

c=Cicle()

成功了

3.继承有抽象方法的非接口类呢?

from abc import ABCMeta, abstractmethod

class Drawable:

    @abstractmethod
    def size(self):
        return 'Drawable size'

    # @abstractmethod
    def draw(self, x, y, scale=1.0):
        pass

    def double_draw(self, x, y):
        self.draw(x, y, scale=2.0)


class Cicle(Drawable):

    def paint(self):
        pass


c=Cicle()

成功====》单独存在抽象并没啥用

猜你喜欢

转载自www.cnblogs.com/wqbin/p/10239515.html
今日推荐