Python, argumentos de palabra clave predeterminados después de argumentos posicionales de longitud variable

81

Pensé que podría usar parámetros con nombre después de parámetros posicionales de longitud variable en una llamada de función en Python 2, pero obtengo un SyntaxErroral importar una clase de Python. Estoy escribiendo con el siguiente método "get", por ejemplo:

class Foo(object):
    def __init__(self):
        print "You have created a Foo."

    def get(self, *args, raw=False, vars=None):
        print len(args)
        print raw
        print vars

El error se parece a:

def get(self, *args, raw=False, vars=None):
                     ^
SyntaxError: invalid syntax

Me gustaría poder llamar al método de varias maneras:

f = Foo()
f.get(arg1, arg2)
f.get(arg1, raw=True)
f.get(arg1, arg2, raw=True, vars=something)

etc.

jkmacc
fuente

Respuestas:

70

Funciona, pero solo en Python 3. Consulte PEP 3102 . Al mirar los documentos de "novedades", parece que no hay un backport 2.x, por lo que no tiene suerte. Tendrá que aceptar cualquier argumento de palabra clave ( **kwargs) y analizarlo manualmente. Puede usar d.get(k, default)para obtener d[k]o defaultsi no está allí. Para eliminar un argumento de kwargs, por ejemplo, antes de llamar a un método de superclase, use d.pop.


Tenga en cuenta que en def get(self, *args, raw=False, vars=None):, raw=Falsey vars=Noneno tienen nada que ver con argumentos de palabras clave. Esos son valores de argumento predeterminados. Los argumentos con un valor predeterminado pueden pasarse posicionalmente, y los argumentos sin un valor predeterminado pueden pasarse por palabra clave:

def f(a=1): pass
f(2)  # works, passing a positionally
def f(a): pass
f(a=2)  # works, passing a by keyword

Del mismo modo, no es necesario que los argumentos de solo palabras clave tengan un valor predeterminado. Ir después del *argsargumento es lo que los marca como solo palabras clave, no la presencia de un valor predeterminado:

def f(*args, a): pass
# a is a mandatory, keyword-only argument
futuro funky
fuente
¡Gracias tanto a ti como a Imran! Su respuesta con el bloque de código de Imran y la sugerencia de cadena de documentos respondió la pregunta perfectamente.
jkmacc
50

La sintaxis de Python no permite argumentos variables en argumentos de función y palabra clave con el valor predeterminado al mismo tiempo. Si debe tener argumentos de palabras clave junto con un número arbitrario de argumentos posicionales, también debe permitir un número arbitrario de argumentos de palabras clave.

Este es un patrón común para proporcionar valores predeterminados para argumentos de palabras clave, además de permitir cualquier número de argumentos posicionales:

def foo(*args, **kwargs):
   raw = kwargs.pop('raw', False)
   vars = kwargs.pop('vars', None)

Si no usa los argumentos de palabras clave adicionales en absoluto, no tiene nada de qué preocuparse. Esto hace que la función sea un poco menos autodocumentada, lo que puede compensar con una cadena de documentos correctamente escrita.

Imran
fuente