传递关键字参数

6 投票
3 回答
3211 浏览
提问于 2025-04-15 12:22

我有一个类里的函数,需要“传递”一个特定的关键字参数:

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参数,而不是用关键字,但如果我在openTablecreateTable中添加其他关键字参数,我就得记得去改调用的地方。我更希望它能自动适应,就像我能用关键字形式那样。

  • 我可以在这里使用**args的形式,这样可以得到一个关键字参数的字典,而不是使用默认参数,但这感觉就像用大锤子打苍蝇(因为需要额外的代码行来正确解析它)。

有没有更好的解决方案呢?

3 个回答

5

我得说,最开始我想的是一个更复杂的问题。但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):
   ...

其他参数会接收任何该方法不认识的关键字参数——而且也不需要对其进行评估。

5

我本来想在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)

这样做可以让位置参数也能生效(如果你真的想让这个功能“传递”下去,这一点很重要)。

9

你做得很好... 只需要在第二个函数调用中去掉 self 就可以了 :)

  return self.createTable(self, tableName, schema, asType=asType)

应该是:

  return self.createTable(tableName, schema, asType=asType)

撰写回答