是否有可能在Python中做抽象类?

如何在Python中创build类或方法摘要?

我尝试重新定义__new__()像这样:

 class F: def __new__(cls): raise Exception("Unable to create an instance of abstract class %s" %cls) 

但是现在如果我创build一个从Finheritance的类G ,像这样:

 class G(F): pass 

那么我也不能实例化G ,因为它调用了它的超类的__new__方法。

有没有更好的方法来定义一个抽象类?

使用abc模块创build抽象类。 使用abstractmethod装饰器声明一个方法abstract,并根据你的Python版本使用三种方法之一来声明一个类的abstract。

在Python 3.4及更高版本中,您可以inheritanceABC 。 在Python的早期版本中,您需要将类的元类指定为ABCMeta 。 指定元类在Python 3和Python 2中有不同的语法。三种可能性如下所示:

 # Python 3.4+ from abc import ABC, abstractmethod class Abstract(ABC): @abstractmethod def foo(self): pass 
 # Python 3.0+ from abc import ABCMeta, abstractmethod class Abstract(metaclass=ABCMeta): @abstractmethod def foo(self): pass 
 # Python 2 from abc import ABCMeta, abstractmethod class Abstract: __metaclass__ = ABCMeta @abstractmethod def foo(self): pass 

无论使用哪种方式,您都无法实例化具有抽象方法的抽象类,但可以实例化提供这些方法的具体定义的子类:

 >>> Abstract() Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: Can't instantiate abstract class Abstract with abstract methods foo >>> class StillAbstract(Abstract): ... pass ... >>> StillAbstract() Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: Can't instantiate abstract class StillAbstract with abstract methods foo >>> class Concrete(Abstract): ... def foo(self): ... print('Hello, World') ... >>> Concrete() <__main__.Concrete object at 0x7fc935d28898> 

老派(pre- PEP 3119 )的方法是在抽象类调用抽象类时调用raise NotImplementedError

 class Abstract(object): def foo(self): raise NotImplementedError('subclasses must override foo()!') class Derived(Abstract): def foo(self): print 'Hooray!' >>> d = Derived() >>> d.foo() Hooray! >>> a = Abstract() >>> a.foo() Traceback (most recent call last): [...] 

这与使用abc模块没有相同的好的属性。 您仍然可以实例化抽象基类本身,直到在运行时调用抽象方法时才会发现错误。

但是,如果你正在处理一小组简单的类,也许只需要几个抽象方法,这种方法比试图通过abc文档要容易一些。

这一个将在python 3中工作

 from abc import ABCMeta, abstractmethod class Abstract(metaclass=ABCMeta): @abstractmethod def foo(self): pass Abstract() >>> TypeError: Can not instantiate abstract class Abstract with abstract methods foo 

是的,您可以使用abc(抽象基类)模块在python中创build抽象类。

这个网站将帮助你: http : //docs.python.org/2/library/abc.html

是的,你可以,使用. abc . abc – 抽象基类模块,这里是一个例子:

Python3.6

 # importing abstract base classes module import abc class GetterSetter(abc.ABC): ''' ABSTRACT BASE CLASSES: - An abstract base class is a kind of 'model' for other classes to be defined. - It is not designed to construct instances, but can be subclassed by regular classes - Abstract classes can define interface, or methods that must be implemented by its subclasses. ''' # Abstract classes are not designed to be instantiated, only to be subclassed # decorator for abstract class @abc.abstractmethod def set_val(self, input): """set the value in the instance""" return @abc.abstractmethod def get_val(self): """Get and return a value from the instance...""" return # Inheriting from the above abstract class class MyClass(GetterSetter): # methods overriding in the GetterSetter def set_val(self, input): self.val = input def get_val(self): return self.val # Instantiate x = MyClass() print(x) # prints the instance <__main__.MyClass object at 0x10218ee48> x = GetterSetter() #throws error, abstract classes can't be instantiated 

Python2.x

 import abc class GetterSetter(object): # meta class is used to define other classes __metaclass__ = abc.ABCMeta # decorator for abstract class @abc.abstractmethod def set_val(self, input): """set the value in the instance""" return @abc.abstractmethod def get_val(self): """Get and return a value from the instance...""" return # Inheriting from the above abstract class class MyClass(GetterSetter): # methods overriding in the GetterSetter def set_val(self, input): self.val = input def get_val(self): return self.val # Instantiate x = GetterSetter() print(x) x = GetterSetter() #throws error, abstract classes can't be instantiated 

在你的代码片段中,你也可以通过为子类中的__new__方法提供一个实现来解决这个问题,同样的:

 def G(F): def __new__(cls): # do something here 

但这是一个黑客,我劝你反对,除非你知道你在做什么。 几乎所有的情况下,我build议你使用abc模块,以前的其他人build议。

另外当你创build一个新的(基类)类时,使它成为子类object ,就像这样: class MyBaseClass(object): 我不知道这是不是很重要,但它有助于保持代码的样式一致性

只是快速添加@ TimGilbert的老学校答案…你可以让你的抽象基类的init ()方法抛出一个exception,这将阻止它被实例化,不是吗?

 >>> class Abstract(object): ... def __init__(self): ... raise NotImplementedError("You can't instantiate this class!") ... >>> a = Abstract() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 3, in __init__ NotImplementedError: You can't instantiate this class!