¿Cómo comprobar si existe una clave en ** kwargs?

111

Python 3.2.3. Había algunas ideas enumeradas aquí , que funcionan en var regulares, pero parece que ** kwargs juegan con reglas diferentes ... entonces, ¿por qué no funciona esto y cómo puedo verificar si existe una clave en ** kwargs?

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

También creo que esto debería funcionar, pero no es así.

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

¿Supongo que porque kwargs es iterable? ¿Tengo que recorrerlo solo para comprobar si hay una clave en particular?

Zamphatta
fuente
4
No hay reglas especiales. Olvidaste las comillas.
Lennart Regebro

Respuestas:

163

Usted quiere

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

Para obtener el valor de errormessage

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

De esta forma, kwargses solo otro dict. Su primer ejemplo, if kwargs['errormessage']significa "obtenga el valor asociado con la clave" mensaje de error "en kwargs, y luego verifique su valor bool". Entonces, si no existe tal clave, obtendrá un KeyError.

Su segundo ejemplo, if errormessage in kwargs:significa "si kwargscontiene el elemento nombrado por" errormessage", y a menos que" errormessage"sea el nombre de una variable, obtendrá un NameError.

Debo mencionar que los diccionarios también tienen un método .get()que acepta un parámetro predeterminado (en sí mismo predeterminado None), por lo que kwargs.get("errormessage")devuelve el valor si esa clave existe y de lo Nonecontrario (de manera similar, kwargs.get("errormessage", 17)hace lo que podría pensar que hace). Cuando no le importa la diferencia entre la clave existente y que tiene Nonecomo valor o la clave no existe, esto puede ser útil.

DSM
fuente
¡Gracias por la explicación adicional! Siempre es bueno que los recién llegados a Python obtengan información general y más ejemplos de lo que es posible y lo que no. En ese espíritu: creo que kwargs.get("errormessage", 17)podría devolver su valor o 17si el mensaje de error no existe, pero no estoy seguro. ¿Es eso correcto?
Honeybear
Ah, sí lo hace. Lo encontré aquí . Gracias ... solo quería estar seguro.
Honeybear
21

Las respuestas de DSM y Tadeck responden directamente a su pregunta.

En mis scripts a menudo uso lo conveniente dict.pop()para tratar con argumentos opcionales y adicionales. Aquí hay un ejemplo de un print()contenedor simple :

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

Luego:

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

Como puede ver, si prefixno está contenido en kwargs, entonces el valor predeterminado ''(cadena vacía) se almacena en la prefixvariable local . Si se da, se está utilizando su valor.

Esta es generalmente una receta compacta y legible para escribir envoltorios para cualquier tipo de función: siempre solo pasa argumentos que no entiendes y ni siquiera sabes si existen. Si siempre pasa *argsy **kwargshace que su código sea más lento, y requiere un poco más de escritura, pero si las interfaces de la función llamada (en este caso print) cambian, no necesita cambiar su código. Este enfoque reduce el tiempo de desarrollo al tiempo que admite todos los cambios de interfaz.

cfi
fuente
Gracias por mostrar cómo asignar un valor predeterminado a prefix.
HBat
11

Es solo esto:

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

Debe verificar si la clave está en el diccionario. La sintaxis para eso es some_key in some_dict(donde some_keyhay algo que se pueda tener con hash, no necesariamente una cadena).

Las ideas que ha vinculado ( estas ideas ) contenían ejemplos para comprobar si existía una clave específica en los diccionarios devueltos por locals()y globals(). Su ejemplo es similar, porque está verificando la existencia de una clave específica en el kwargsdiccionario (el diccionario que contiene argumentos de palabras clave).

Tadeck
fuente
3

¡Una forma es agregarlo usted mismo! ¿Cómo? Al fusionarse kwargscon un montón de valores predeterminados. Esto no será apropiado en todas las ocasiones, por ejemplo, si no conoce las claves de antemano. Sin embargo, si lo son, aquí hay un ejemplo simple:

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)

Los valores predeterminados se establecen en el diccionario args, que incluye todas las claves que esperamos. Primero verificamos si hay claves inesperadas en kwargs. Luego actualizamos argscon kwargslo que sobrescribirá los nuevos valores que el usuario haya establecido. No necesitamos probar si existe una clave, ahora la usamos argscomo diccionario de argumentos y no necesitamos más kwargs.

cdarke
fuente
1

Puedes descubrir esas cosas fácilmente por ti mismo:

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

hello(what="world")
Christian Thieme
fuente
13
Quite el "fácil" y luego es una mejor respuesta. Si fuera fácil para todos, entonces no necesitaríamos este sitio. Encontrar el inoperador en sí mismo no es fácil si nunca ha programado y / o es nuevo en Python. Solo se insinúa en dict.get()y dict.setdefault()ayuda.
cfi
1
if kwarg.__len__() != 0:
    print(kwarg)
YeongHwa Jin
fuente