我在this way中实现了一个复合模式:
1)“抽象”组件是:
class Component(object):
"""Basic Component Abstraction"""
def __init__(self, *args, **kw):
raise NotImplementedError("must be subclassed")
def status(self):
"""Base Abstract method"""
raise NotImplementedError("must be implemented")
2)一片叶子:
class Leaf(Component):
"""Basic atomic component
"""
def __init__(self, *args, **kw):
self.dict = {}
def status(self):
"""Retrieves properties
"""
return self.dict
问题是pylint当然会产生这个警告:
Leaf.__init__: __init__ method from base class 'Component' is not called
但是在我的Leaf中我不能要求:
def __init__(self, *args, **kw):
Component.__init__(self, *args, **kw)
self.dict = {}
没有提出异常。
我必须忽略pylint警告或编码错误吗?
答案 0 :(得分:4)
抽象初始化器是个坏主意。您的代码可能会发展,以便您希望在根组件中进行一些初始化。即使你没有为什么要求执行初始化程序。对于某些子类,空的初始值设定项是可接受的选择。
如果您不想要任何Component类的实例,请在初始化程序中检查它:
class Component(object):
def __init__(self, **kwargs):
assert type(self) != Component, "Component must not be instantiated directly"
class Leaf(Component):
def __init__(self, some, args, **kwargs):
# regular initialization
Component.__init__(self, **kwargs)
答案 1 :(得分:2)
补充马库斯思想的另一个建议:
如果你真的必须,我建议你使用__new __并检查给定的对象类型。当它是“组件”时,您可以触发您的例外:
class Component(object):
"""Basic Component Abstraction"""
def __new__(objType, *args, **kwargs):
if objType == Component:
raise NotImplementedError("must be subclassed")
return object.__new__(type, *args, **kwargs)
创建子类时,objType将是!= Component,一切都会好的!
答案 2 :(得分:2)
将您的类Component重命名为AbstractComponent应该有所帮助。如果不应该由子类调用,则不要在基类中提供__init__
方法。
答案 3 :(得分:1)
您希望保证基类Component不是实例化的。这是一个在C ++等其他编程语言中很常见的高级客户(你可以将构造函数设置为私有,以防止直接使用)。
但Python不支持它。 Python不支持所有编程概念,也更“动态”。所以初始化是以“Pythonic”方式完成的,因此不支持你的想法。
Python比其他语言更基于信任 - 因此,例如静态变量不受支持,私有变量也只是以有限的方式。
你可以做什么(当你不信任模块的用户时) - 你可以通过命名它来“隐藏基类” - “_Component” - 使它成为一个内部秘密。但当然这可能会带来其他麻烦。
答案 4 :(得分:1)
这样编码也不错,但根本不需要组件的__init__
。如果您需要,可以忽略pylint,但最好只从组件中删除__init__
。
拥抱动力!