代码之家  ›  专栏  ›  技术社区  ›  dabadaba

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

  •  64
  • dabadaba  · 技术社区  · 9 年前

    我试图声明一个抽象类 A 对于具有默认行为的构造函数:所有子类都必须初始化一个成员 self.n :

    from abc import ABCMeta
    
    class A(object):
        __metaclass__ = ABCMeta
    
        def __init__(self, n):
            self.n = n
    

    然而,我不想让 A.

    a = A(3)
    

    这不会产生任何错误,而我认为应该是这样。

    那么:在定义构造函数的默认行为时,如何定义不可实例化的抽象类?

    6 回复  |  直到 6 年前
        1
  •  82
  •   Mike Müller    9 年前

    __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)
    

    TypeError: Can't instantiate abstract class A with abstract methods __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)
    

    同样有效:

    TypeError:无法用抽象方法\uu init实例化抽象类A__
    
        2
  •  8
  •   gipsy    9 年前

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

    用法

    class B(A):
      pass
    a = A(1)  # Will throw exception
    b = B(1)  # Works fine as expected.
    
        3
  •  5
  •   Ashwini Chaudhary    9 年前

    __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)
    

    输出:

    >>> 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
    
        4
  •  4
  •   Ignacio Vergara Kausel    9 年前

    @abc.abstractmethod

        5
  •  2
  •   Tiger    6 年前

    您可以实现以下功能:

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

        6
  •  1
  •   John Conde    5 年前

    我不想让A类被实例化,因为它是一个抽象类。问题是,这实际上是允许的

    抽象类是包含一个或多个抽象方法的类。在您的案例代码中,仍然是一个抽象类,它应该提供“抽象类不能实例化”的行为。

    i、 e添加decorator@abstractmethod。 以下代码在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
    

    输出: