python 抽象基类(abc)

设置ABCMeta元类

  抽象类是一类用于继承,但是无需实现具体方法的类,它会创建一些子类必须实现的方法签名。抽象类在定义和强制类抽象方面非常有用,它类似于其他变成语言里面的接口概念,无需实现具体方法。

  从概念上来讲,有一种实现抽象类的方式是对类方法进行存根,然后在类方法被访问的时候直接抛出NotImplementedError异常。这样可以防止子类在没有重写类方法之前直接访问父类的类方法。

像这样:

class Fruit:

    def check_ripeness(self):
        raise NotImplementedError("check_ripeness method not implemented!")

class Apple(Fruit):
    pass

a = Apple()
a.check_ripeness() # raises NotImplementedError

  以这种方式创建抽象类可以防止不恰当的使用没有被重写的类方法,当然我们鼓励在子类中定义这些抽象类方法,但却不强制定义。利用abc模块可以防止子类在没有成功地重写父类及其祖先类中抽象类方法之前被实例化。

from abc import ABCMeta

class AbstractClass(object):
    # metaclass 属性必须要设置成类属性
    __metaclass__ = ABCMeta

   # abstractmethod装饰器, 用来注册该方法为未绑定方法
   @abstractmethod
   def virtual_method_subclasses_must_define(self):
       # 可以直接不写,也可以提供基础的实现
       # 注意,通常来说,如果不写的话,它会隐式的返回None,
       # 但是通过这样注册的话,它不会强制返回None

  现在就可以简化子类和重写抽象类方法了:

class Subclass(AbstractClass):
    def virtual_method_subclasses_must_define(self):
        return ‘whatever‘

为什么要使用ABCMeta和abstractmethod,如何使用它们

  抽象基类(ABCs) 强制派生类实现基类中的特定方法。

  为了理解它是如何工作的以及为什么要使用它,我们举个例子来看一下。比如说,我们有一个基类 "MontyPython",里面有两个方法(joke和punchline)必须要在所有的派生类中实现:

class MontyPython:
    def joke(self):
        raise NotImplementedError()

    def punchline(self):
        raise NotImplementedError()

class ArgumentClinic(MontyPython):
    def joke(self):
        return "Hahahahahah"

  当我们实例化出一个对象,并且调用它的这两个方法,在调用punchline的时候会报错:

>>> sketch = ArgumentClinic()
 >>> sketch.punchline()
NotImplementedError 

  但是,我们还是可以正常的实例化ArgumentClinic类,并不会出现任何报错。事实上,只有在我们访问punchline()方法的时候才会报错。

  如果使用抽象基类(ABC)模块就不会出现这种问题。通过下面的例子我们来看一下它是如何工作的:

from abc import ABCMeta, abstractmethod

class MontyPython(metaclass=ABCMeta):
    @abstractmethod
    def joke(self):
        pass

    @abstractmethod
    def punchline(self):
        pass

class ArgumentClinic(MontyPython):
    def joke(self):
        return "Hahahahahah"

  现在当我们再实例化这个不完整的类的时候,它马上就会报TypeErrors的错误!

>>> c = ArgumentClinic()
TypeError:
"Can‘t instantiate abstract class ArgumentClinic with abstract methods punchline"

  这种情况下,我们可以通过在子类中实现这两个抽象类都TypeErrors的错误。

class ArgumentClinic(MontyPython):
    def joke(self):
        return "Hahahahahah"

    def punchline(self):
        return "Send in the constable!"

  现在,你就可以正常的实例化ArgumentClinic类了。

时间: 2024-08-23 11:14:08

python 抽象基类(abc)的相关文章

Python 接口:从协议到抽象基类

抽象基类的常见用途:实现接口时作为超类使用.然后,说明抽象基类如何检查具体子类是否符合接口定义,以及如何使用注册机制声明一个类实现了某个接口,而不进行子类化操作.最后,说明如何让抽象基类自动“识别”任何符合接口的类——不进行子类化或注册. Python文化中的接口和协议 接口在动态类型语言中是怎么运作的呢?首先,基本的事实是,Python语言没有 interface 关键字,而且除了抽象基类,每个类都有接口:类实现或继承的公开属性(方法或数据属性),包括特殊方法,如__getitem__ 或 _

流畅python学习笔记:第十一章:抽象基类

__getitem__实现可迭代对象.要将一个对象变成一个可迭代的对象,通常都要实现__iter__.但是如果没有__iter__的话,实现了__getitem__也可以实现迭代.我们还是用第一章扑克牌的例子来看下 class FrenchDeck:     ranks=[str(n) for n in range(2,11)] + list('JQKA')     suits='spades diamonds clubs hearts'.split()     def __init__(sel

python(七):元类与抽象基类

一.实例创建 在创建实例时,调用__new__方法和__init__方法,这两个方法在没有定义时,是自动调用了object来实现的.python3默认创建的类是继承了object. class A(object): def __init__(self, *args, **kwargs): self.name, self.age, self.gender = args[:3] def __new__(cls, *args, **kwargs): print("__new__ has called.

6.1 numbers--数值抽象基类

6. 数值和数学库 本库主要提供了数值和数学相关的函数处理以及数据类型.numbers模块定义了抽象的数值类型,math和cmath模块主要包括不同的数学函数,比如用来计算浮点数和复数.decimal模块支持十进制数值表示,可以用任何精度进行运算. 6.1 numbers--数值抽象基类 本模块主要按文档(PEP 3141)定义了数值抽象基类. class numbers.Number 数值类的基类,如果你只是想检查一个参数x是否是Number类型,可以使用函数isinstance(x, Num

C++ 纯虚函数与抽象基类

在C++ 中,虚函数可以很好的实现多态,然而也有一定的局限,这个局限在于,虚函数必须在基类中定义,哪怕是空的实现. 例如下面这段代码编译时就会出错: class Base { virtual void print(); }; class Derived:Base { void print() { cout << "Derived" <<endl; } }; 因为Base类中的虚函数print()没有定义. 而在实际编程时我们往往会遇到无法给基类的函数定义的情况,

制造抽象基类--《C++必知必会》 条款33

抽象类,含有纯虚函数的类,不可以创建对象. 然而,有时我们并不需要某个函数定义为纯虚函数,但是任然希望此类像抽象类一样,不可以创建对象. 方法1:通过确保类中不存在共有构造函数来模拟抽象基类的性质.意味着,我们必须至少显示地声明一个构造函数和一个复制构造函数,防止编译器隐式公有的内联的构造函数.声明为protected ,既允许派生类的构造函数使用他们,同时阻止创建对象. class ABC{ protected: ABC(); ABC(const ABC&); }; 方法2:让一个类成为抽象基

定义接口或者抽象基类

你想定义一个接口或抽象类,并且通过执行类型检查来确保子类实现了某些特定的方法. 解决方案: 使用 abc 模块可以很轻松的定义抽象基类 from abc import ABCMeta, abstractmethod class IStream(metaclass=ABCMeta): @abstractmethod def read(self, maxbytes=-1): pass @abstractmethod def write(self, data): pass 抽象类的一个特点是它不能直接

C# 面向对象 , 抽象基类

抽象基类 关键字,  abstract abstract class SSS { public void aaa() { } } 作为抽象基类, 只能在 继承关系 中 担任父类的角色,不能出现在其他地方. 不能建对象. 抽象类里面的 方法(函数)不能直接实现, 必须在子类实现. 关键字  override ---------只对属性有用(带大括号的) class override EEE : SSS { public void aaa() { } } 抽象新建 SSS p = new EEE()

6、面向对象以及winform的简单运用(抽象基类与接口)

抽象类与抽象方法 1.书写规范: 在类前面加上abstract关键字,就成为了抽象类:在一个方法前面加上abstract关键字,就成为了抽象方法(抽象方法不能有实现方法,直接在后面加分号) 例: abstract class Chouxiang //抽象类 { public abstract void fangfa(); //抽象方法 } 2.抽象类的注意事项: 1)当一个类变为抽象类之后就不能作为对象来使用了,无法new出来 2)抽象方法必须放在抽象类里面(但抽象类中不一定有抽象方法) 3)没