2009-11-11 48 views
12

我是一个对象的子类,以覆盖我想要添加某些功能的方法。我不想完全替换它,或者添加一个不同名称的方法,但只需向该方法添加可选参数即可与超类方法兼容。 是否可以使用*args**kwargs来传递超类的所有参数,并仍然使用默认值添加可选参数? 我直觉想出了下面的,但它不工作:将一个关键字参数添加到重写的方法并使用** kwarg

class A(object): 
    def foo(self, arg1, arg2, argopt1="bar"): 
     print arg1, arg2, argopt1 

class B(A): 
    def foo(self, *args, argopt2="foo", **kwargs): 
     print argopt2 
     A.foo(self, *args, **kwargs) 


b = B() 
b.foo("a", "b", argopt2="foo") 

当然,我可以得到它的工作时,我明确添加父类的方法的所有参数:

class B(A): 
    def foo(self, arg1, arg2, argopt1="foo", argopt2="bar"): 
     print argopt2 
     A.foo(self, arg1, arg2, argopt1=argopt1) 

这样做的正确方法是什么?我必须知道并明确声明所有重写的方法参数吗?

回答

10
class A(object): 
    def foo(self, arg1, arg2, argopt1="bar"): 
     print arg1, arg2, argopt1 

class B(A): 
    def foo(self, *args, **kwargs): 
     argopt2 = kwargs.get('argopt2', default_for_argopt2) 
     # remove the extra arg so the base class doesn't complain. 
     del kwargs['argopt2'] 
     print argopt2 
     A.foo(self, *args, **kwargs) 


b = B() 
b.foo("a", "b", argopt2="foo") 
+5

您可以使用弹出而不是GET + DEL。 – iny 2009-11-11 15:27:05

+0

我总是忘记dict.pop! – 2009-11-11 15:37:31

+3

当'argopt2'未传递时,您的示例失败并出现'KeyError'。使用'kwargs.pop('argopt2',default_for_argopt2)'是修复它的最简单方法。 – 2009-11-11 17:26:10

1

当继承和压倒一切的方法,一个必须决定是否使用super()是一个好主意,this page是好了点。

super()应尽量避免,如文章作者可能是:我是说,super()有必须遵循的一些非常重要的prerequisits如果你不想super()回来咬你。

+0

http://fuhm.org/super-harmful/是一个很好的阅读。谢谢泰迪 – unutbu 2009-11-11 19:07:17

6

怎样做的正确方法,我 必须知道并明确声明的重写方法的参数都 ?

如果要覆盖所有的情况下(而不是仅仅依赖于呼叫者经常做的事情你的方式,例如,总是叫你只能用名通过了额外的参数,从不按位置)你必须以编码(或动态发现)许多有关您所覆盖的方法签名的知识 - 这并不奇怪:继承是一种强大的耦合形式,而重载方法是耦合呈现的一种方式。

可以动态发现超类的通过inspect.getargspec方法的参数,以确保你正确地调用它......但如果类试图做同样的事情自省技术可能很麻烦(一旦你知道你的超类的方法接受了*a和/或**kw,你可以做的不过是向上传递所有相关的参数,并希望在调用一个不太容忍的版本之前,上游方法链最终进行适当的清理, 。

当你设计一个包装器时,这样的价格可能是值得的,这个包装器应该被动态地应用于各种各样的签名(特别是因为在一个装饰器设置中你可以安排一次花费巨大的内省费用你正在装饰每个函数,而不是每次调用结果包装器时)。在像你这样的情况下,你最好知道自己的子类化(子类化是强大的耦合:盲目地做,绝对不可取!),这似乎不太可能成为一种有价值的技术,所以你不妨明白参数明确。

是的,如果超类的代码剧烈变化(例如,,通过改变方法签名),你也必须修改子类 - 这是继承的价格(的一部分)。整体价格的大幅足够新Go编程语言完全不无它 - 迫使你到Gang of 4的优秀建议适用于prefer composition over inheritance。在Python完全禁欲继承只会是不切实际的,但使用它清醒和适度(并接受的价格,你将支付的耦合而言,当你做)仍然可取。

+0

对签名变更的警告。但我认为有一个例外:可以更改构造函数的签名。问题中描述的问题也适用于构造函数。 – 2009-11-11 17:33:36

相关问题