tipos - python ejemplo de declaración de variable
Cómo obtener el nombre de variable original de la variable pasada a una función (7)
La respuesta de @Ivo Wetzel funciona en el caso de que la llamada de función se realice en una línea, como
e = 1 + 7
c = 3
foo(e, 100, b=c)
En caso de que la llamada a la función no esté en una línea, como:
e = 1 + 7
c = 3
foo(e,
1000,
b = c)
debajo del código funciona:
import inspect, ast
def foo(a, f, b):
frame = inspect.currentframe()
frame = inspect.getouterframes(frame)[1]
string = inspect.findsource(frame[0])[0]
nodes = ast.parse(''''.join(string))
i_expr = -1
for (i, node) in enumerate(nodes.body):
if hasattr(node, ''value'') and isinstance(node.value, ast.Call)
and hasattr(node.value.func, ''id'') and node.value.func.id == ''foo'' # Here goes name of the function:
i_expr = i
break
i_expr_next = min(i_expr + 1, len(nodes.body)-1)
lineno_start = nodes.body[i_expr].lineno
lineno_end = nodes.body[i_expr_next].lineno if i_expr_next != i_expr else len(string)
str_func_call = ''''.join([i.strip() for i in string[lineno_start - 1: lineno_end]])
params = str_func_call[str_func_call.find(''('') + 1:-1].split('','')
print(params)
Conseguirás:
[u''e'', u''1000'', u''b = c'']
Pero aún así, esto podría romperse.
¿Es posible obtener el nombre de la variable original de una variable pasada a una función? P.ej
foobar = "foo"
def func(var):
print var.origname
Así que eso:
func(foobar)
Devoluciones:
>>foobar
EDITAR:
Todo lo que traté de hacer fue hacer una función como:
def log(soup):
f = open(varname+''.html'', ''w'')
print >>f, soup.prettify()
f.close()
.. y hacer que la función genere el nombre del archivo a partir del nombre de la variable que se le pasa.
Supongo que si no es posible, tendré que pasar la variable y el nombre de la variable como una cadena cada vez.
No puedes. Se evalúa antes de pasarse a la función. Todo lo que puedes hacer es pasarlo como una cadena.
Otra forma de probar si sabe cómo se verá el código de llamada es usar traceback
:
def func(var):
stack = traceback.extract_stack()
filename, lineno, function_name, code = stack[-2]
code
contendrá la línea de código que se usó para llamar a func
(en su ejemplo, sería la cadena func(foobar)
). Puedes analizar eso para sacar el argumento
Para agregar a la respuesta de Michael Mrozek, puede extraer los parámetros exactos contra el código completo de la siguiente manera:
import re
import traceback
def func(var):
stack = traceback.extract_stack()
filename, lineno, function_name, code = stack[-2]
vars_name = re.compile(r''/((.*?)/).*$'').search(code).groups()[0]
print vars_name
return
foobar = "foo"
func(foobar)
# PRINTS: foobar
Parece que Ivo me golpeó para inspect
, pero aquí hay otra implementación:
import inspect
def varName(var):
lcls = inspect.stack()[2][0].f_locals
for name in lcls:
if id(var) == id(lcls[name]):
return name
return None
def foo(x=None):
lcl=''not me''
return varName(x)
def bar():
lcl = ''hi''
return foo(lcl)
bar()
# ''lcl''
Por supuesto, puede ser engañado:
def baz():
lcl = ''hi''
x=''hi''
return foo(lcl)
baz()
# ''x''
Moral: no lo hagas.
Si quieres una relación de pares de valor clave, ¿quizás sería mejor usar un diccionario?
... o si está tratando de crear alguna documentación automática a partir de su código, tal vez algo como Doxygen ( http://www.stack.nl/~dimitri/doxygen/ ) podría hacer el trabajo por usted?
EDITAR: Para dejar en claro, no recomiendo usar esto EN ABSOLUTO, se romperá, es un desastre, de todos modos no lo ayudará, pero es factible para fines de entretenimiento / educación.
Puedes hackear el módulo de inspect
, no lo recomiendo, pero puedes hacerlo ...
import inspect
def foo(a, f, b):
frame = inspect.currentframe()
frame = inspect.getouterframes(frame)[1]
string = inspect.getframeinfo(frame[0]).code_context[0].strip()
args = string[string.find(''('') + 1:-1].split('','')
names = []
for i in args:
if i.find(''='') != -1:
names.append(i.split(''='')[1].strip())
else:
names.append(i)
print names
def main():
e = 1
c = 2
foo(e, 1000, b = c)
main()
Salida:
[''e'', ''1000'', ''c'']