Como verificar se existe uma chave no ** kwargs?

111

Python 3.2.3. Algumas ideias foram listadas aqui , que funcionam em vars normais, mas parece que ** kwargs seguem regras diferentes ... então por que isso não funciona e como posso verificar se existe uma chave em ** kwargs?

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

Eu também acho que isso deveria funcionar, mas não -

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

Estou supondo porque kwargs é iterável? Tenho que iterar por ele apenas para verificar se uma chave específica está lá?

Zamphatta
fonte
4
Não existem regras especiais. Você apenas esqueceu as aspas.
Lennart Regebro

Respostas:

164

Você quer

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

Para obter o valor de errormessage

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

Dessa forma, kwargsé apenas mais uma dict. Seu primeiro exemplo if kwargs['errormessage'],, significa "obter o valor associado à chave" mensagem de erro "em kwargs e, em seguida, verificar seu valor bool". Portanto, se essa chave não existir, você receberá um KeyError.

Seu segundo exemplo if errormessage in kwargs:,, significa "se kwargscontém o elemento nomeado por" errormessage"e, a menos que" errormessage"seja o nome de uma variável, você obterá um NameError.

Devo mencionar que os dicionários também têm um método .get()que aceita um parâmetro padrão (ele próprio assumindo o padrão None), de modo que kwargs.get("errormessage")retorna o valor se essa chave existir e de Noneoutra forma (da mesma forma kwargs.get("errormessage", 17)que você pode pensar que faz). Quando você não se importa com a diferença entre a chave existente e tendo Nonecomo valor ou a chave não existente, isso pode ser útil.

DSM
fonte
Obrigado pela explicação extra! É sempre bom para iniciantes em Python obter algumas informações básicas e mais exemplos do que é possível e do que não é. Com esse espírito: Eu acho que kwargs.get("errormessage", 17)pode retornar seu valor ou 17se errormessage não existir - mas não tenho certeza. Isso é correto?
Honeybear
Sim, é verdade. Encontrei aqui . Obrigado ... só queria ter certeza.
Honeybear
21

As respostas do DSM e do Tadeck respondem diretamente à sua pergunta.

Em meus scripts, costumo usar o conveniente dict.pop()para lidar com argumentos opcionais e adicionais. Aqui está um exemplo de um print()invólucro simples :

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

Então:

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

Como você pode ver, se prefixnão estiver contido em kwargs, o padrão ''(string vazia) está sendo armazenado na prefixvariável local . Se for fornecido, então seu valor está sendo usado.

Esta é geralmente uma receita compacta e legível para escrever wrappers para qualquer tipo de função: sempre apenas repasse os argumentos que você não entende e nem mesmo sabe se eles existem. Se você sempre passa *argse **kwargstorna seu código mais lento e requer um pouco mais de digitação, mas se as interfaces da função chamada (neste caso print) mudarem, você não precisa mudar seu código. Essa abordagem reduz o tempo de desenvolvimento ao mesmo tempo que oferece suporte a todas as alterações de interface.

cfi
fonte
Obrigado por mostrar como atribuir um valor padrão a prefix.
HBat
11

É apenas isso:

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

Você precisa verificar se a chave está no dicionário. A sintaxe para isso é some_key in some_dict(onde some_keyé algo com hash, não necessariamente uma string).

As ideias que você vinculou ( essas ideias ) continham exemplos para verificar se existia uma chave específica nos dicionários retornados por locals()e globals(). Seu exemplo é semelhante, porque você está verificando a existência de uma chave específica no kwargsdicionário (o dicionário que contém argumentos de palavras-chave).

Tadeck
fonte
3

Uma maneira é adicionar você mesmo! Quão? Ao mesclar kwargscom um monte de padrões. Isso não será apropriado em todas as ocasiões, por exemplo, se as chaves não forem conhecidas por você com antecedência. No entanto, se forem, aqui está um exemplo simples:

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)

Os padrões são definidos no dicionário args, que inclui todas as chaves que esperamos. Primeiro verificamos se existem chaves inesperadas nos kwargs. Em seguida, atualizamos argscom o kwargsqual substituirá quaisquer novos valores que o usuário tenha definido. Não precisamos testar se existe uma chave, agora usamos argscomo nosso dicionário de argumentos e não precisamos mais disso kwargs.

cdarke
fonte
1

Você pode descobrir essas coisas facilmente por si mesmo:

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

hello(what="world")
Christian Thieme
fonte
13
Remova o "fácil" e será uma resposta melhor. Se fosse fácil para todos, não precisaríamos deste site. Encontrar o inoperador em si não é fácil se você nunca programou e / ou é novo no Python. Ele está apenas sendo sugerido na ajuda dict.get()e dict.setdefault().
cfi
1
if kwarg.__len__() != 0:
    print(kwarg)
YeongHwa Jin
fonte