2009-05-31 11 views
26

Czy istnieje sposób, aby w czasie wykonywania poznać nazwę zmiennej (z kodu)? lub czy nazwy var zostały zapomniane podczas kompilacji (kod bajtowy czy nie)?pobieranie nazwy zmiennej w python w środowisku wykonawczym?

np.

 
>>> vari = 15 
>>> print vari.~~name~~() 
'vari' 

uwaga: Mówię o zwykłych zmiennych danych typu (int, str, liście ...)

+6

Nie musisz wpisywać nazwy zmiennej, aby uzyskać jej nazwę? –

+2

Tak, cóż, minęło już 3 lata temu i nie pamiętam, dlaczego to pytanie miało sens. Ale woa! jest bardzo popularny, więc coś w tym jest. –

+0

Oto przykład użycia: istnieją zmienne foo, bar, baz, chcę uzyskać słownik dokładnie taki jak {'foo': foo, 'bar': bar, 'baz': baz}. Na pewno mogę wypisać to, co właśnie zrobiłem, ale nie bardzo zwięźle. 'locals()', moim zdaniem, przekazują zbyt wiele informacji, nie są doskonałe. Oczekuję, że funkcja taka jak 'magic_func ([foo, bar, baz])', która zwróci słownik, który chcę – ZZY

Odpowiedz

2

Oto podstawowa (może dziwna) funkcja, która pokazuje nazwę jej argumentu ... idea jest analizowanie kodu i poszukiwanie wywołań funkcji (dodanej w Init metoda może pomóc, aby znaleźć nazwę instancji, choć o bardziej skomplikowanej analizy kodu)

def display(var): 
    import inspect, re 
    callingframe = inspect.currentframe().f_back 
    cntext = "".join(inspect.getframeinfo(callingframe, 5)[3]) #gets 5 lines 
    m = re.search("display\s+\(\s+(\w+)\s+\)", cntext, re.MULTILINE) 
    print m.group(1), type(var), var 

uwaga: się wiele wierszy z kodu wywołującego pomaga w przypadku, gdy połączenie zostało podzielone, jak w poniższym przykładzie:

display(
     my_var 
     ) 

ale będzie produkować nieoczekiwany rezultat w tej sprawie:

display(first_var) 
display(second_var) 

Jeśli nie masz kontroli nad formatem projektu można jeszcze poprawić kod do wykrywania i zarządzania różne sytuacje ...

Ogólnie myślę, statyczna analiza kodu może produkować bardziej wiarygodne wyniki, ale jestem zbyt leniwy, aby to sprawdzić teraz

10

Nazwy zmiennych utrzymują w skompilowanego kodu (tak jak np dir wbudowaną może praca), ale mapowanie odbywa się od nazwy do wartości, a nie odwrotnie. Jeśli więc istnieje kilka zmiennych, na przykład: 23, nie ma sposobu, aby odróżnić je od siebie bazując tylko na wartości 23.

29

Nazwy zmiennych nie zostają zapomniane, można uzyskać dostęp do zmiennych (i sprawdzić, które zmienne mają) przez introspekcję, np.

>>> i = 1 
>>> locals()["i"] 
1 

Jednak ponieważ w Pythonie nie ma żadnych wskazówek, nie ma możliwości odniesienia do zmiennej bez wpisania jej nazwy. Jeśli więc chcesz wydrukować nazwę zmiennej i jej wartość, możesz przejść przez locals() lub podobną funkcję. ([i] staje [1] i nie ma sposobu, aby pobrać informację, że 1 rzeczywiście pochodziła z i).

+0

rozwiązuje mój przypadek. następnie dokonuję odwrotnego wyszukiwania na ich wartości i znajduję ich nazwy. dzięki. –

+5

Najtrudniejsze jest to, że jeśli masz tylko 'i ', to niemożliwe jest znalezienie jego nazwy w' locals() '. Rozważ "i = 1; j = 1; '. Po tym "locals() [" i "] to locals() [" j "] '. Jeśli wszystko, co masz, to 'i ', to przejście przez locals() spowoduje znalezienie" i "lub" j "jako nazwy. –

+1

D. prawdopodobnie ma zamiar powiedzieć "Jeśli wszystko co masz to" 1 "[...]" – akaihola

0

Jeszcze wczoraj widziałem blogu z kodu, który robi właśnie to działa. Oto link:

http://pyside.blogspot.com/2009/05/finding-objects-names.html

+0

"Przepraszamy, strona, której szukasz w tym blogu, nie istnieje." –

+2

@StuartWoodward: archive.org ma kopię: http://web.archive.org/web/20090624235438/http://pyside.blogspot.com/2009/05/finding-objects-names.html –

+0

To będzie działa również w swojej obecnej formie, jeśli jest używany w głównym pliku pythona, jeśli jest zaimportowany, otworzy niewłaściwy plik, więc trzeba go dostosować. – will

3

To będzie pracować dla prostych typów danych (str, int, float, lista itp)

def my_print(var_str) : 
    print var_str+':', globals()[var_str] 
+0

Trzeba tylko zauważyć, że jeśli masz, powiedz "ix = 200", to wywołaj tę funkcję za pomocą 'my_print (" ix ")'. – sdaau

4

Oto funkcja użyć do druku wartości zmiennych, działa na lokalne oraz globalne:

import sys 
def print_var(var_name): 
    calling_frame = sys._getframe().f_back 
    var_val = calling_frame.f_locals.get(var_name, calling_frame.f_globals.get(var_name, None)) 
    print (var_name+':', str(var_val)) 

więc następujący kod:

global_var = 123 
def some_func(): 
    local_var = 456 
    print_var("global_var") 
    print_var("local_var") 
    print_var("some_func") 

some_func() 

produkuje:

global_var: 123 
local_var: 456 
some_func: <function some_func at 0x10065b488> 
+0

Tego właśnie szukałem. Jednak teraz jestem ciekawy, czy można to rozszerzyć, aby działało dla dowolnego wyrażenia, biorąc pod uwagę kontekst, w którym wywoływany jest 'print_var'. Jednym z przykładów użycia byłoby wydrukowanie zarówno nazwy, jak i wartości pola obiektu (np. 'Print_var ('myobject.x')') – anishpatel

+0

To nie było zbyt trudne: https://gist.github.com/anishpatel/e32f9cdc1df55692f418 – anishpatel

2

Można to zrobić, to po prostu nie dość.

import inspect, sys 


def addVarToDict(d, variable): 
    lineNumber = inspect.currentframe().f_back.f_lineno 
    with open(sys.argv[0]) as f: 
     lines = f.read().split("\n") 

    line = lines[lineNumber-1] 

    varName = line.split("addVarToDict")[1].split("(")[1].split(",")[1].split(")")[0].strip() 
    d[varName] = variable 


d = {} 

a=1 

print d # {} 
addVarToDict(d,a) 
print d # {'a': 1} 
Powiązane problemy