【问题标题】:What is the way of enforcing explicit initialization of parent class by an implementer?实现者强制执行父类的显式初始化的方式是什么?
【发布时间】:2018-05-12 12:03:29
【问题描述】:

考虑以下示例 sn-p

import abc


class BASE(metaclass=abc.ABCMeta):
    def __init__(self, name):
        assert name is not None, "Name must be provided."
        self.num = 3

    @abc.abstractmethod
    def compute(self):
        pass


class CHILD(BASE):
    def __init__(name):
         '''
         '''


    def compute(self):
        return self.num + 34

在执行时会出现以下错误:

AttributeError: 'CHILD' 对象没有属性 'num'

在目前的情况下,BASE 没有被初始化,因为如果我们如下添加一个打印函数,它绝对不会打印任何东西。

class BASE(metaclass=abc.ABCMeta):
    def __init__(self, name):
        print(name)
        assert name is not None, "Name must be provided."
        self.num = 3

我们可以在这个类设计中做些什么来确保从BASE 子类化的实现器必须显式调用BASE 的初始化程序吗?

【问题讨论】:

  • 只确保定义了self.num 就足够了吗?如果是这样,@abstractproperty 装饰器可以解决问题……或者堆叠@abstractmethod@property(Python 3.3+)。更多详情:stackoverflow.com/questions/5960337/…
  • 。嗯。在这种情况下,是的,这就足够了。但我正在考虑更复杂和更大规模的项目,例如,父类可能会用于初始化一些数据库或进行一些身份验证或做一些其他不平凡的工作。在这种情况下,强制的显式初始化会很重要(或者我认为)。
  • 我明白了……这必须在子类的实例被实例化时发生?也就是说,不是在子类本身创建的时候?
  • 我认为,如果您通过设计推测,由子类编写者来确保他们调用 super。
  • +1 @kyle 的评论 - 在 Python 中,通常假设我们都是同意的成年人。这意味着,如果您正确记录了您的基类以及它应该如何被子类化(包括调用它的__init__() 方法),那么假设使用它的成年人会阅读文档并尊重它的期望并不是不合理的。

标签: python python-3.x


【解决方案1】:

我们可以在这个类设计中做任何事情来确保 从 BASE 子类化的实现者必须显式调用初始化器 基地的?

我猜你可以这样做:

class BASE(metaclass=abc.ABCMeta):
    '''
    when subclassing this class, ensure you explicitly 
    call super().__init__() for this parent class
    '''
    def __init__(self, name):
        assert name is not None, "Name must be provided."
        self.num = 3

来自 cmets 部分:

我只是想了解现实世界中的问题、设计 以确保不会发生此类错误

我做了很多子类,我没有明确调用父类的super().__init__()。所以我不确定你是否可以说所有子类都必须调用父类__init__以避免“错误”(正如你所说的那样)。由父类的创建者来正确记录如何进行子类化,然后由子类的创建者决定是否这样做。不是你可以“强制执行”的东西

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-03-19
    • 1970-01-01
    • 2017-05-01
    • 1970-01-01
    • 2018-06-15
    • 2012-01-14
    • 1970-01-01
    • 2020-12-22
    相关资源
    最近更新 更多