Dada la función Python:
def a_method(arg1, arg2):
pass
¿Cómo puedo extraer el número y los nombres de los argumentos? Es decir, dado que tengo una referencia func
, quiero func.[something]
que regrese ("arg1", "arg2")
.
El escenario de uso para esto es que tengo un decorador, y deseo usar los argumentos del método en el mismo orden en que aparecen para la función real como una clave. Es decir, ¿cómo se vería el decorador que impreso "a,b"
cuando llamo a_method("a", "b")
?
Respuestas:
Eche un vistazo al
inspect
módulo: esto hará la inspección de las diferentes propiedades del objeto de código por usted.Los otros resultados son el nombre de las variables * args y ** kwargs, y los valores predeterminados proporcionados. es decir.
Tenga en cuenta que algunas llamadas no pueden ser introspectables en ciertas implementaciones de Python. Por ejemplo, en CPython, algunas funciones integradas definidas en C no proporcionan metadatos sobre sus argumentos. Como resultado, obtendrá un
ValueError
si lo usainspect.getfullargspec()
en una función incorporada.Desde Python 3.3, puede usar
inspect.signature()
para ver la firma de la llamada de un objeto invocable:fuente
(4,)
correspondec
específicamente al parámetro de la palabra clave ?inspect.getargspec
está en desuso , pero el reemplazo lo estáinspect.getfullargspec
.En CPython, el número de argumentos es
y sus nombres están al comienzo de
Estos son detalles de implementación de CPython, por lo que probablemente esto no funcione en otras implementaciones de Python, como IronPython y Jython.
Una forma portátil de admitir argumentos de "transferencia" es definir su función con la firma
func(*args, **kwargs)
. Esto se usa mucho, por ejemplo , en matplotlib , donde la capa API externa pasa muchos argumentos de palabras clave a la API de nivel inferior.fuente
*args
, por ejemplo:def foo(x, *args, y, **kwargs): # foo.__code__.co_argcount == 1
En un método de decorador, puede enumerar los argumentos del método original de esta manera:
Si
**kwargs
son importantes para usted, entonces será un poco complicado:Ejemplo:
fuente
Creo que lo que estás buscando es el método local:
fuente
La versión de Python 3 es:
El método devuelve un diccionario que contiene args y kwargs.
fuente
[:fn.__code__.co_argcount]
es muy importante si está buscando los argumentos de la función; de lo contrario, también incluye los nombres creados dentro de la función.Aquí hay algo que creo que funcionará para lo que quieres, usando un decorador.
Ejecútelo, producirá el siguiente resultado:
fuente
Python 3.5+:
Entonces anteriormente:
Ahora:
Probar:
Dado que tenemos la función 'función' que toma el argumento 'arg', esto se evaluará como Verdadero, de lo contrario, como Falso.
Ejemplo de la consola de Python:
fuente
¡En Python 3. + con el
Signature
objeto en mano, una manera fácil de obtener una asignación entre los nombres de los argumentos y los valores es usar elbind()
método de la Firma !Por ejemplo, aquí hay un decorador para imprimir un mapa como ese:
fuente
Aquí hay otra forma de obtener los parámetros de la función sin usar ningún módulo.
Salida:
fuente
Devuelve una lista de nombres de argumentos, se ocupa de parciales y funciones regulares:
fuente
Actualización para la respuesta de Brian :
Si una función en Python 3 tiene argumentos de solo palabras clave, entonces debe usar
inspect.getfullargspec
:produce esto:
fuente
En python 3, a continuación es para hacer
*args
y**kwargs
en undict
(usoOrderedDict
para python <3.6 para mantener losdict
pedidos):fuente
inspect.signature
es muy lento. La forma más rápida esfuente
Para actualizar un poco la respuesta de Brian , ahora hay un buen backport de
inspect.signature
que se puede utilizar en las versiones anteriores de Python:funcsigs
. Entonces mi preferencia personal iría porPor diversión, si estás interesado en jugar con
Signature
objetos e incluso crear funciones con firmas aleatorias dinámicamente, puedes echar un vistazo a mimakefun
proyecto.fuente
¿Qué pasa
dir()
yvars()
ahora?Parece hacer exactamente lo que se le pide súper simplemente ...
Debe llamarse desde el ámbito de la función.
Pero tenga cuidado de que devolverá todas las variables locales, así que asegúrese de hacerlo al comienzo de la función si es necesario.
También tenga en cuenta que, como se señaló en los comentarios, esto no permite que se haga desde fuera del alcance. Entonces, no es exactamente el escenario de OP, pero aún coincide con el título de la pregunta. De ahí mi respuesta.
fuente