Сквозные ключевые аргументы - PullRequest
5 голосов
/ 19 июня 2009

У меня есть функция класса, которая должна "пройти" через определенный аргумент ключевого слова:

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 ]

9 голосов
/ 19 июня 2009

Вы делаете все правильно ... Просто уберите self во втором вызове функции:)

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

должно быть:

  return self.createTable(tableName, schema, asType=asType)
5 голосов
/ 19 июня 2009

Я бы написал комментарий к посту Юргена, но мне нужно написать пример кода. Вот немного более общая версия:

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)

Это позволит позиционным аргументам также быть эффективными (что важно, если вы действительно хотите, чтобы это было «сквозным».

5 голосов
/ 19 июня 2009

Я должен сказать, что сначала подумал о более сложной проблеме. Но ответ Дэвида Волера абсолютно верен. Это просто дублирующая личность, которая создает проблему. Таким образом, позиционные параметры выходят за пределы строки, и 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):
   ...

Параметр others съедает любые ключевые параметры, неизвестные методу - его также не нужно оценивать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...