2012-09-08 20 views
8

Estoy aprendiendo a usar argumentos posicionales en Python y también tratar de ver cómo funcionan cuando se mezcla con los argumentos por defecto: -Uso de los argumentos por defecto antes de argumentos posicionales

def withPositionalArgs(ae=9,*args): 
    print 'ae= ', ae 
    print 'args = ', args 


a=1 
b=2 
c=[10,20] 

withPositionalArgs(a,b,c) 

Esto me da la salida:

ae= 1 
args = (2, [10, 20]) 

como se puede ver, a se considera que es un valor que pasaba por ae y b, así como c se consideran los argumentos posicionales.

Por lo tanto, ahora estoy tratando de asignar 10 para ae mientras llama withPositionalArgs:

withPositionalArgs(ae=10,b,c) 

Pero, no puedo hacerlo. Me sale el error:

SyntaxError: non-keyword arg after keyword arg 

Mi pregunta es:

estoy haciendo correctamente? ¿Se permite el argumento predeterminado o una buena práctica antes de los argumentos posicionales en las funciones de Python?

+2

Se le podría llamar con 'withPositionalArgs (10, B, C)'. –

+0

Lo "sorprendente" es que llamar ... (1, ae = 2) arroja 'TypeError: ...() obtuvo varios valores para el argumento de palabra clave 'ae''. –

Respuesta

9

En Python2, no está permitido poner argumentos que tengan un valor predeterminado antes de argumentos posicionales.

Los argumentos posicionales deben estar primero, luego los argumentos con los valores predeterminados (o, al llamar a la función, los argumentos de la palabra clave), luego *args, y luego **kwargs.

Esta orden es necesaria tanto para la definición de la función como para las llamadas a funciones.

En Python3, el orden ha sido relajado. (Por ejemplo, *args puede aparecer antes de un argumento de palabra clave en la definición de función). See PEP3102.

+0

@unubtu: ¿No está permitido tanto en la definición como en la llamada de función? ¿O solo en 1 lugar? – GodMan

+0

Este es el orden que se debe usar para la definición y la llamada a la función. Sin embargo, en la llamada de función, puede hacer cosas como 'foo (c = 1, ae = 3, b = 2)'. Es decir, el orden de los argumentos puede mezclarse al proporcionarles argumentos de palabra clave. – unutbu

+0

Puede parecer tonto preguntar, pero el comentario de Vaughn Cato sobre mi respuesta me permite pasar los argumentos como se requiere, y Python no da ningún error. Por lo tanto, debo modificar su respuesta como: 'En Python, en llamadas a funciones, no está permitido poner argumentos que tengan un parámetro predeterminado antes de argumentos posicionales. Pero, ¿se te permite hacerlo en la definición de función? – GodMan

2

Creo que debemos hacer la distinción de los valores predeterminados frente a pasar en los argumentos arbitrarios/pares clave-valor. El comportamiento sin valores por defecto es el mismo:

def f(ae,*args, **kwargs): 
    print 'ae  = ', ae 
    print 'args = ', args 
    print 'kwargs = ', kwargs 

la forma en que hemos escrito esto significa que el primer argumento pasado a f en la tupla args, que es f(1,2,3,a=1,b=2) (la secuencia va argumentos explícitos, * args, ** kwargs.) Aquí: ae = 1, args = (2,3), kwargs = {'a': 1, 'b': 2}.

Si tratamos de pasar en f(1,2,3,a=1,ae=3) nos lanzamos un TypeError: f() got multiple values for keyword argument 'ae', ya que el valor de ae se intenta cambiar dos veces.

.

Una forma de evitar esto es sólo para establecer ae cuando se prescribe explícitamente, que podría (después de la línea de def):

def g(*args, **kwargs): 
    kwargs, kwargs_temp = {"ae": 9}, kwargs 
    kwargs.update(kwargs_temp) #merge kwargs into default dictionary 

y esta vez g(1,2,3,a=1,ae=3) conjuntos args=(1,2,3), kwargs={a=1,ae=3}.

Sin embargo, sospecho que esto no es una buena práctica ...

1

Python3 tiene un orden relajado.

Ahora usted puede hacer algo como:

def withPositionalArgs(*args, ae=9): 
    print('ae=', ae) 
    print('args =', args) 
a=1 
b=2 
c=[10, 20] 
withPositionalArgs(a, b, c, ae=7) 
Cuestiones relacionadas