python2.7: 在实例方法中传递kwargs
如果我想把一个函数里的参数列表直接传给另一个函数,我可以用 locals 函数。不过,如果我在一个实例方法里,这就不行了,因为 self 不能作为关键字参数传递。我可以先创建一个 locals 的字典,然后把 self 删除掉。但我在想,是否有更优雅的方法来做到这一点,因为我经常遇到这个问题。
class MyObj:
def test(self, a=1, b=2, c=3, d=4):
return [a,b,c,d]
class MyVerboseObj(MyObj):
def test(self, a=1, b=2, c=3, d=4):
print "RUNNING TEST a=%d"%a
kwargs = locals()
del kwargs["self"]
return MyObj.test(self, **kwargs)
MyVerboseObj().test()
有没有更好的方法把 MyVerboseObj.test 的参数列表传给 MyObj.test?
** 更新 **
这是一个简化的例子,用来说明我的问题。一个更实际的例子可能是这样的:
class GenericShow:
def __init__(self, path):
self.path = path
def getRenderPath(self, extn="jpg", colspace="rgb"):
return "%s/render_%s.%s"%(self.path, colspace, extn)
def hasGenericShowHandler(self):
try:
import GenericShowHandler
return True
except: pass
class UkShow(GenericShow):
def getRenderPath(self, extn="jpg", colspace="rgb"):
if self.hasGenericShowHandler():
kwargs = locals()
kwargs.pop("self")
return GenericShow.getRenderPath(self, **kwargs)
else:
return "%s/blah/render_%s.%s"%(path, colspace, extn)
show = UkShow("/jobs/test")
show.hasGenericShowHandler()
print show.getRenderPath()
我有很多展示对象,它们的变量由不同的模块定义,并且命名方式也不一样——我想创建一些具有共同功能的展示对象。
2 个回答
0
使用 locals()
通常不是个好主意。这种做法容易让人困惑,而且对代码的修改很脆弱,因为如果你添加了任何局部变量,就会搞乱你的调用。
我建议使用更明确的方式:
class MyObj:
def test(self, a=1, b=2, c=3, d=4):
return [a,b,c,d]
class MyVerboseObj(MyObj):
def test(self, a=1, b=2, c=3, d=4):
print "RUNNING TEST a=%d"%a
return MyObj.test(self, a, b, c, d)
MyVerboseObj().test()
我知道这样做比较麻烦,但可以避免一些问题。而且这样效率更高。
另外,如果你不介意失去函数的签名,可以直接接受 *args, **kwargs
作为你重写函数的参数:
class MyObj:
def test(self, a=1, b=2, c=3, d=4):
return [a,b,c,d]
class MyVerboseObj(MyObj):
def test(self, *args, **kwargs):
print "RUNNING TEST"
return MyObj.test(self, *args, **kwargs)
MyVerboseObj().test()
在这个版本中访问 a
会有点麻烦,但因为你在第二个例子中并不太关心这些参数,所以这可能是个更简单的解决方案。
顺便提一下:当你的继承结构变得更加复杂(比如多重继承)时,你可能想开始使用 super() 方法:
class MyObj:
def test(self, a=1, b=2, c=3, d=4):
return [a,b,c,d]
class MyVerboseObj(MyObj):
def test(self, *args, **kwargs):
print "RUNNING TEST"
super(MyObj, self).test(*args, **kwargs)
MyVerboseObj().test()
2
如果你不想覆盖父类的函数(因为你想使用它),那么只需要给它起个不同的名字,就可以避免覆盖了!
class MyObj:
def base_test(self, a=1, b=2, c=3, d=4):
return [a,b,c,d]
class MyVerboseObj(MyObj):
def test(self, a=1, b=2, c=3, d=4):
print "RUNNING TEST a=%d"%a
kwargs = locals()
del kwargs["self"]
return self.base_test(**kwargs)
print MyVerboseObj().test()