Обнаружить неверный аргумент ключевого слова - PullRequest
4 голосов
/ 03 августа 2011

У меня есть следующая функция:

def foo(**kwargs):
  if not kwargs:
    # No keyword arguments? It's all right. Set defaults here...
  elif ('start_index' or 'end_index') in kwargs:
    # Do something here...
  else:
    # Catch unexpected keyword arguments
    raise TypeError("%r are invalid keyword arguments" % (kwargs.keys())

Вопрос:

Я хочу убедиться, что единственными допустимыми аргументами ключевых слов являются start_index или end_index. Все остальное вызовет ошибку, даже если смешать с действительными. Каков рецепт поваренной книги, чтобы убедиться, что принимаются только start_index или end_index? Да, я ищу рецепт поваренной книги, но не знаю, как его найти. Я не уверен, что использование структуры if-elif-else также является правильным способом сделать это.

Ответы [ 4 ]

12 голосов
/ 03 августа 2011

Зачем вам нужно **kwargs здесь? Just

def foo(start_index=None, end_index=None):

и Python выполнит всю проверку для вас.

5 голосов
/ 03 августа 2011

Ради полноты, Вот альтернатива, которая все еще использует **kwargs.

def foo(**kwargs):
  start_index = kwargs.pop('start_index', STARTINDEX_DEFAULT)
  end_index = kwargs.pop('end_index', ENDINDEX_DEFAULT)
  if kwargs:
    # Catch unexpected keyword arguments
    raise TypeError("%r are invalid keyword arguments" % (kwargs.keys())
  # Do something here...

Но , вы не должны использовать это, когда вы не совсемнужно, используйте обычные параметры со значениями по умолчанию (как в ответе Романа Боднарчука).

Случаи, когда вам может понадобиться это, когда вы также хотите использовать *args, и вам нужен способ отличить аргументы ключевого слова отпроизвольно человек позиционные аргументы.использование **kwargs таким образом заставляет аргументы ключевого слова передаваться как ключевые слова;Позиционный аргумент никогда не сможет найти свой путь в **kwargs.

Другая причина заключается в том, что вы можете действительно различать параметр по умолчанию и явный параметр, который является значением по умолчанию.None часто используется в качестве значения по умолчанию для аргументов, указывающих «аргумент не применяется», но иногда вам действительно нужно интерпретировать None как нечто отличное от значения по умолчанию.Проверка наличия или отсутствия ключа в диктовке **kwargs позволяет точно различать эти случаи.(Альтернативой является создание экземпляра подкласса object, единственной целью которого является значение по умолчанию для конкретного аргумента этой конкретной функции)

1 голос
/ 03 августа 2011

Если вы действительно хотите использовать **kwargs, я бы написал так:

def foo(**kwargs):
    # Define default values for all keys
    args = {'start_index': 0, 'end_index': -1}

    # Get the keys passed in that aren't in args
    extraargs = set(kwargs) - set(args)
    if extraargs:
        raise TypeError("Invalid arguments: %s" % list(extraargs))

    # Overwrite the default values with the passed-in values
    args.update(kwargs)

    # Now, do stuff with the values in args

Но все это сложный, медленный способ дублирования встроенных функций. Не делайте этого, если вам действительно не нужно.

0 голосов
/ 03 августа 2011

В любом случае получить ключи от dict так же просто, как использовать .get, например.

kwargs.get('WIDTH',500)

таким образом, если он не находит WIDTH в качестве ключа, вы получаете 500.

...