简体   繁体   English

如何在 Python 中为抽象类定义构造函数实现?

[英]How define constructor implementation for an Abstract Class in Python?

I am trying to declare an abstract class A with a constructor with a default behavior: all subclasses must initialize a member self.n :我正在尝试使用具有默认行为的构造函数声明抽象类A :所有子类都必须初始化成员self.n

from abc import ABCMeta

class A(object):
    __metaclass__ = ABCMeta

    def __init__(self, n):
        self.n = n

However, I do not want to let the A class be instantiated because, well, it is an abstract class.但是,我不想让A类被实例化,因为它是一个抽象类。 The problem is, this is actually allowed:问题是,这实际上是允许的:

a = A(3)

This produces no errors, when I would expect it should.这不会产生错误,而我希望它应该。

So: how can I define an un-instantiable abstract class while defining a default behavior for the constructor?那么:如何在为构造函数定义默认行为的同时定义不可实例化的抽象类?

Making the __init__ an abstract method:使__init__成为抽象方法:

from abc import ABCMeta, abstractmethod

class A(object):
    __metaclass__ = ABCMeta

    @abstractmethod
    def __init__(self, n):
        self.n = n


if __name__ == '__main__':
    a = A(3)

helps:帮助:

TypeError: Can't instantiate abstract class A with abstract methods __init__

Python 3 version: Python 3 版本:

from abc import ABCMeta, abstractmethod

class A(object, metaclass=ABCMeta):

    @abstractmethod
    def __init__(self, n):
        self.n = n


if __name__ == '__main__':
    a = A(3)

Works as well:也有效:

TypeError: Can't instantiate abstract class A with abstract methods __init__

A not so elegant solution can be this:一个不太优雅的解决方案可能是这样的:

class A(object):
  def __init__(self, n):
    if self.__class__ == A:
      raise Exception('I am abstract!')
    self.n = n

Usage用法

class B(A):
  pass
a = A(1)  # Will throw exception
b = B(1)  # Works fine as expected.

您还应该使用@abc.abstractmethod装饰器将方法定义为抽象方法。

You can override __new__ method to prevent direct instantiation.您可以覆盖__new__方法以防止直接实例化。

class A(object):
    __metaclass__ = ABCMeta

    def __new__(cls, *args, **kwargs):
        if cls is A:
            raise TypeError(
                "TypeError: Can't instantiate abstract class {name} directly".format(name=cls.__name__)
            )
        return object.__new__(cls)

Output:输出:

>>> A()
Traceback (most recent call last):
  File "<ipython-input-8-3cd318a12eea>", line 1, in <module>
    A()
  File "/Users/ashwini/py/so.py", line 11, in __new__
    "TypeError: Can't instantiate abstract class {name} directly".format(name=cls.__name__)
TypeError: TypeError: Can't instantiate abstract class A directly

You can implement something like below :您可以实现如下内容:

from abc import ABC
class A(ABC):
    def __init__(self, n):
        self.n = n
        super(A,self).__init__()

Instantiating this class would throw an error实例化这个类会抛出一个错误

I do not want to let the A class be instantiated because, well, it is an abstract class.我不想让 A 类被实例化,因为它是一个抽象类。 The problem is, this is actually allowed问题是,这实际上是允许的

Python on its own doesn't provide abstract classes. Python 本身不提供抽象类。 'abc' module which provides the infrastructure for defining Abstract Base Classes. 'abc' 模块提供定义抽象基类的基础结构。

Abstract classes are classes that contain one or more abstract methods.抽象类是包含一个或多个抽象方法的类。 In your case code still an abstract class that should provide "Abstract classes cannot be instantiated" behavior.在您的情况下,代码仍然是一个抽象类,应该提供“无法实例化抽象类”行为。

If you don't want to allow, program need corrections: ie add decorator @abstractmethod.如果您不想允许,程序需要更正:即添加装饰器@abstractmethod。 Below code executed in python 3.6下面的代码在python 3.6中执行

from abc import ABC, abstractmethod

class Myabs(ABC):

    def __init__(self, connection):
        self.connection = connection
        print("1. calling from base init : {}".format(self.connection))
        super(Myabs, self).__init__()
    @abstractmethod
    def fun1(self, val):
        pass

class D(Myabs):
    def fun1(self, val="hi"):
        print("calling from D: fun1")


object0 = Myabs('connection') # Python 3.6.9

output:输出:

ClassConcept/abs_class.py Traceback (most recent call last): File "ClassConcept/abs_class.py", line 19, in object0 = Myabs('connection') # Python 3.6.9 TypeError: Can't instantiate abstract class Myabs with abstract methods fun1 ClassConcept/abs_class.py 回溯(最近一次调用最后一次):文件“ClassConcept/abs_class.py”,第 19 行,在 object0 = Myabs('connection') # Python 3.6.9 TypeError:无法用抽象实例化抽象类 Myabs方法乐趣1

Process finished with exit code 1进程以退出代码 1 结束

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在 Python 的抽象 class 实现中使用 self? - How to use self in an abstract class implementation in Python? 抽象类实现在python中不起作用 - Abstract class implementation not working in python 如何在python中定义一个抽象类并强制实现变量 - how to define an abstract class in python and force implement variables Python中是否有“Addable”协议或抽象基class? 如果不是,人们将如何定义它? - Is there an "Addable" protocol or abstract base class in Python? If not how would one define it? 如何在python中定义抽象元类 - How to define an abstract metaclass in python Python3 - 如何从现有抽象类定义抽象子类? - Python3 - How does one define an abstract subclass from an existing abstract class? Python:带有具体实现细节的测试摘要 class - Python: Testing abstract class with concrete implementation details 如何在抽象 class 方法中引用抽象共享实现中的子类属性 - How to refer to subclass property in abstract shared implementation in abstract class method 如何强制抽象类的子类应该在 Python 中定义一个特定的内部类 - How to enforce that subclass of abstract class should define a particular inner class in Python 如何为抽象基础 class 实现构造函数? - How to implement a constructor for an abstract base class?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM