5

类层次结构和构造函数是相关的。来自子类的参数需要传递给它们的父类。

所以,在 Python 中,我们最终会得到这样的结果:

class Parent(object):
    def __init__(self, a, b, c, ka=None, kb=None, kc=None):
        # do something with a, b, c, ka, kb, kc

class Child(Parent):
    def __init__(self, a, b, c, d, e, f, ka=None, kb=None, kc=None, kd=None, ke=None, kf=None):
        super(Child, self).__init__(a, b, c, ka=ka, kb=kb, kc=kc)
        # do something with d, e, f, kd, ke, kf

想象一下这有十几个子类和大量参数。添加新参数变得非常繁琐。

当然,可以完全放弃命名参数并使用 *args 和 **kwargs,但这会使方法声明模棱两可。

在 Python (2.6) 中是否有优雅地处理这个问题的模式?

“优雅”是指我想减少参数出现的次数。a、b、c、ka、kb、kc 都出现了 3 次:在 Child 构造函数中,在对 Parent 的 super() 调用中,以及在 Parent 构造函数中。

理想情况下,我想为 Parent 的init指定一次参数,而在 Child 的init中只指定附加参数。

我想做这样的事情:

class Parent(object):
    def __init__(self, a, b, c, ka=None, kb=None, kc=None):
        print 'Parent: ', a, b, c, ka, kb, kc

class Child(Parent):
    def __init__(self, d, e, f, kd='d', ke='e', kf='f', *args, **kwargs):
        super(Child, self).__init__(*args, **kwargs)
        print 'Child: ', d, e, f, kd, ke, kf

x = Child(1, 2, 3, 4, 5, 6, ka='a', kb='b', kc='c', kd='d', ke='e', kf='f')

不幸的是,这不起作用,因为 4、5、6 最终分配给了 kd、ke、kf。

是否有一些优雅的 python 模式可以完成上述操作?

4

3 回答 3

8

无论参数命名如何,“十几个子类和大量参数”听起来都是一个问题。

我怀疑一点点重构可以剥离一些Strategy对象,从而简化这个层次结构并使超级复杂的构造函数消失。

于 2009-07-29T20:20:00.567 回答
3

好吧,我能看到的唯一解决方案是混合使用列出的变量以及 *args 和 **kwargs,如下所示:

class Parent(object):
    def __init__(self, a, b, c, ka=None, kb=None, kc=None):
        pass

class Child(Parent):
    def __init__(self, d, e, f, *args, kd=None, ke=None, kf=None, **kwargs):
        Parent.__init__(self, *args, **kwargs)
        pass

这样,您可以查看每个类需要哪些参数,而无需重新键入它们。

需要注意的一件事是,当它变为 (d, e, f, a, b, c) 时,您会丢失所需的顺序 (a, b, c, d, e, f)。我不确定是否有办法让 *args 在其他非命名参数之前。

于 2009-07-29T20:18:33.193 回答
1

我尝试将参数分组到它们自己的对象中,例如,我将有一个 DirectoryContext 和 ServerContext 对象,而不是传递 sourceDirectory、targetDirectory、temporaryDirectory、serverName、serverPort。

如果上下文对象开始有更多的行为或逻辑,它可能会导致这里提到的策略对象。

于 2009-07-29T21:01:05.663 回答