我有一个类,它应该包含几个其他类作为其属性 - 我相信组合将是正确的术语。现在,我想初始化包含类的属性,具体取决于它们是否已在包含类中设置。在下面的示例中,我将使用None
覆盖两个次要类的默认值,这是我不想要的:
class OneAttribute:
def __init__(self,a=1):
self.a = a
class TwoAttributes:
def __init__(self,b=2,c=3):
self.b = b
self.c = 3
class SuperClass:
def __init__(self,a=None,b=None,c=None):
'''
This would override the defaults in the
other two classes, which is bad.
'''
self.one = OneAttribute(a=a)
self.two = TwoAttributes(b=b,c=c)
我也可以像下面那样定义包含类,但是不是很好也不可扩展简直太可怕了:
Class SuperClass:
def __init__(self,a=None,b=None,c=None):
if a is not None:
self.one = OneAttribute(a=a)
else:
self.one = OneAttribute()
if b is not None and c is not None:
self.two = TwoAttributes(b=b, c=c)
elif b is not None:
self.two = TwoAttributes(b=b)
elif c is not None:
self.two = TwoAttributes(c=c)
else:
self.two = TwoAttributes()
我想要实现的可能是一个糟糕的设计决定吗?
答案 0 :(得分:2)
一种解决方案是允许您的班级接受额外的关键字参数
class OneAttribute:
def __init__(self,a=1,**kwargs):
self.a = a
class TwoAttributes:
def __init__(self,b=2,c=3,**kwargs):
self.b = b
self.c = c
然后您可以简单地接受容器类
中的关键字参数class SuperClass:
def __init__(self, **kwargs):
self.one = OneAttribute(**kwargs)
self.two = TwoAttributes(**kwargs)
缺点是,如果你将一个额外的参数传递给另一个内部类,那么它将无法检测到。
避免这个问题是可能的,但需要一些黑魔法:首先你要像往常一样声明内部类:
class OneAttribute:
def __init__(self,a=1):
self.a = a
class TwoAttributes:
def __init__(self,b=2,c=3):
self.b = b
self.c = c
然后你发现使用内省他们期望的参数是什么
def parms_of(f):
return f.__code__.co_varnames[:f.__code__.co_argcount]
并仅将它们传递给内部类构造函数
def filter_kwargs(kwargs, f):
s = set(parms_of(f))
return dict((k, v) for k, v in kwargs.items()
if k in s)
class SuperClass:
def __init__(self, **kwargs):
self.one = OneAttribute(**filter_kwargs(kwargs, OneAttribute.__init__))
self.two = TwoAttributes(**filter_kwargs(kwargs, TwoAttributes.__init__))