Как проверить, существует ли ключ в ** kwargs?

111

Python 3.2.3. Здесь перечислены некоторые идеи , которые работают с обычными var, но похоже, что ** kwargs играют по другим правилам ... так почему это не работает и как я могу проверить, существует ли ключ в ** kwargs?

if kwargs['errormessage']:
    print("It exists")

Я тоже думаю, что это должно сработать, но это не так -

if errormessage in kwargs:
    print("yeah it's here")

Я предполагаю, потому что kwargs повторяется? Нужно ли мне перебирать его, чтобы проверить, есть ли там конкретный ключ?

Замфатта
источник
4
Особых правил нет. Вы просто забыли цитаты.
Леннарт Регебро,

Ответы:

165

Вы хотите

if 'errormessage' in kwargs:
    print("found it")

Чтобы получить значение errormessage

if 'errormessage' in kwargs:
    print("errormessage equals " + kwargs.get("errormessage"))

Таким образом, kwargsэто просто другое dict. Ваш первый пример, if kwargs['errormessage']означает "получить значение, связанное с ключом errormessage" в kwargs, а затем проверить его значение типа bool ". Так что, если такого ключа нет, вы получите файл KeyError.

Ваш второй пример, if errormessage in kwargs:означает «если kwargsсодержит элемент, названный« errormessage», и если« errormessage»не является именем переменной, вы получите NameError.

Я должен упомянуть, что словари также имеют метод, .get()который принимает параметр по умолчанию (сам по умолчанию None), так что он kwargs.get("errormessage")возвращает значение, если этот ключ существует, и в Noneпротивном случае (аналогично тому kwargs.get("errormessage", 17), что вы могли подумать). Если вас не волнует разница между существующим ключом и имеющимся Noneв качестве значения или несуществующим ключом, это может быть удобно.

DSM
источник
Спасибо за дополнительное объяснение! Новички в Python всегда могут получить некоторую справочную информацию и дополнительные примеры того, что возможно, а что нет. В том же духе: я думаю, kwargs.get("errormessage", 17)может вернуть свое значение или 17если сообщение об ошибке не существует, но я не уверен. Это правильно?
Honeybear
Ах да, это так. Нашел здесь . Спасибо ... просто хотел убедиться.
Honeybear
21

Ответы DSM и Tadeck напрямую отвечают на ваш вопрос.

В своих скриптах я часто использую удобные dict.pop()для работы с необязательными и дополнительными аргументами. Вот пример простой print()оболочки:

def my_print(*args, **kwargs):
    prefix = kwargs.pop('prefix', '')
    print(prefix, *args, **kwargs)

Затем:

>>> my_print('eggs')
 eggs
>>> my_print('eggs', prefix='spam')
spam eggs

Как видите, если prefixне содержится в kwargs, то значение по умолчанию ''(пустая строка) сохраняется в локальной prefixпеременной. Если он указан, то используется его значение.

Как правило, это компактный и читаемый рецепт для написания оболочек для любого типа функции: всегда просто передавайте аргументы, которые вы не понимаете и даже не знаете, существуют ли они. Если вы всегда проходите *argsи **kwargsделаете свой код медленнее и требует немного большего набора текста, но если интерфейсы вызываемой функции (в данном случае print) изменяются, вам не нужно менять свой код. Такой подход сокращает время разработки, поддерживая все изменения интерфейса.

CFI
источник
Спасибо за то, что показали, как присвоить значение по умолчанию prefix.
HBat
11

Это просто:

if 'errormessage' in kwargs:
    print("yeah it's here")

Вам нужно проверить, есть ли ключ в словаре. Синтаксис для этого: some_key in some_dict(где some_keyчто-то хешируемое, не обязательно строка).

Идеи, которые вы связали ( эти идеи ), содержат примеры для проверки наличия определенного ключа в словарях, возвращаемых locals()и globals(). Ваш пример аналогичен, потому что вы проверяете наличие определенного ключа в kwargsсловаре (словарь, содержащий аргументы ключевого слова).

Тадек
источник
3

Один из способов - добавить его самостоятельно! Как? Путем слияния kwargsс кучей значений по умолчанию. Это не всегда подходит, например, если ключи вам заранее не известны. Однако, если они есть, вот простой пример:

import sys

def myfunc(**kwargs):
    args = {'country':'England','town':'London',
            'currency':'Pound', 'language':'English'}

    diff = set(kwargs.keys()) - set(args.keys())
    if diff:
        print("Invalid args:",tuple(diff),file=sys.stderr)
        return

    args.update(kwargs)            
    print(args)

Значения по умолчанию устанавливаются в словаре args, который включает все ожидаемые нами ключи. Сначала мы проверяем, есть ли в kwargs какие-либо неожиданные ключи. Затем мы обновляем argsс kwargsкоторой будет перезаписывать новые значения , которые пользователь установил. Нам не нужно проверять, существует ли ключ, теперь мы используем argsсловарь аргументов и больше не нуждаемся в нем kwargs.

cdarke
источник
1

Вы можете легко обнаружить эти вещи самостоятельно:

def hello(*args, **kwargs):
    print kwargs
    print type(kwargs)
    print dir(kwargs)

hello(what="world")
Кристиан Тим
источник
13
Уберите «легкий», и тогда это будет лучший ответ. Если бы всем было легко, то этот сайт нам бы не понадобился. Найти inоператор сам по себе непросто, если вы никогда не программировали и / или новичок в Python. На это только намекают dict.get()и dict.setdefault()помогают.
cfi