是否有可能在Python中做抽象类?
如何在Python中创build类或方法摘要?
我尝试重新定义__new__()
像这样:
class F: def __new__(cls): raise Exception("Unable to create an instance of abstract class %s" %cls)
但是现在如果我创build一个从F
inheritance的类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!