传递关键字参数
我有一个类里的函数,需要“传递”一个特定的关键字参数:
def createOrOpenTable(self, tableName, schema, asType=Table):
if self.tableExists(tableName):
return self.openTable(tableName, asType=asType)
else:
return self.createTable(self, tableName, schema, asType=asType)
当我调用这个函数时,会出现这样的错误:
TypeError: createTable() got multiple values for keyword argument 'asType'
有没有办法“传递”这样的关键字参数呢?
我想过几个解决办法,但都不是最理想的。从最差到最好的排序如下:
我可以把一个或多个函数的关键字名称改掉,但我想在这三个函数中都用同样的关键字,因为这个参数的意思是一样的。
我可以通过位置来传递
asType
参数,而不是用关键字,但如果我在openTable
或createTable
中添加其他关键字参数,我就得记得去改调用的地方。我更希望它能自动适应,就像我能用关键字形式那样。我可以在这里使用
**args
的形式,这样可以得到一个关键字参数的字典,而不是使用默认参数,但这感觉就像用大锤子打苍蝇(因为需要额外的代码行来正确解析它)。
有没有更好的解决方案呢?
3 个回答
我得说,最开始我想的是一个更复杂的问题。但David Wolever的回答完全正确。这里的问题就是重复使用了同一个参数,这导致位置参数出现了混乱,asType被当作位置参数传了一次,然后又作为关键字参数传了一次!
一个更有趣的问题是,当你想要增强被调用的函数(比如例子中的createTable)时,如何在不每次都增强中间函数的情况下做到这一点。在这里,**args的解决方案就派上用场了:
举个例子:
def createOrOpenTable(self, tableName, schema, **args):
if self.tableExists(tableName):
return self.openTable(tableName, **args)
else:
return self.createTable(tableName, schema, **args)
通过这种方式,可以增强createTable和openTable的参数,而不需要再修改createOrOpenTable。
当create和openTable可以有不同的关键字参数时,当然这两个函数必须这样定义:
def createTable(self, tableName, schema, asType=None, **others):
...
其他参数会接收任何该方法不认识的关键字参数——而且也不需要对其进行评估。
我本来想在Juergen的帖子下评论,但我需要写个代码示例。这里有一个更通用的版本:
def createOrOpenTable(self, tableName, schema, *args, **argd):
if self.tableExists(tableName):
return self.openTable(tableName, *args, **argd)
else:
return self.createTable(tableName, schema, *args, **argd)
这样做可以让位置参数也能生效(如果你真的想让这个功能“传递”下去,这一点很重要)。
你做得很好... 只需要在第二个函数调用中去掉 self
就可以了 :)
return self.createTable(self, tableName, schema, asType=asType)
应该是:
return self.createTable(tableName, schema, asType=asType)