W tym wątku omówiono, jak uzyskać nazwę funkcji jako ciąg znaków w Pythonie: Jak uzyskać nazwę funkcji w postaci ciągu?
Jak mogę zrobić to samo dla zmiennej? W przeciwieństwie do funkcji zmienne Pythona nie mają __name__
atrybutu.
Innymi słowy, jeśli mam zmienną taką jak:
foo = dict()
foo['bar'] = 2
Szukam funkcji / atrybutu np. retrieve_name()
W celu stworzenia DataFrame w Pandas z tej listy , gdzie nazwy kolumn podane są przez nazwy rzeczywistych słowników:
# List of dictionaries for my DataFrame
list_of_dicts = [n_jobs, users, queues, priorities]
columns = [retrieve_name(d) for d in list_of_dicts]
pip3 install python-varname==0.1.5
; zaimportowane za pomocąfrom varname import nameof
test = {}
print(varname.nameof(test))
for i in [0]:
print(varname.nameof(test))
pierwszy wydruk dajetest
, wydruk w pętli podnosi sięVarnameRetrievingError: Callee's node cannot be detected.
v0.2.0
Jedynymi obiektami w Pythonie, które mają nazwy kanoniczne, są moduły, funkcje i klasy, i oczywiście nie ma gwarancji, że ta nazwa kanoniczna ma jakiekolwiek znaczenie w jakiejkolwiek przestrzeni nazw po zdefiniowaniu funkcji lub klasy lub zaimportowaniu modułu. Nazwy te można również modyfikować po utworzeniu obiektów, więc nie zawsze są one szczególnie godne zaufania.
To, co chcesz zrobić, nie jest możliwe bez rekurencyjnego chodzenia po drzewie nazwanych obiektów ; nazwa to jednostronne odniesienie do obiektu. Typowy lub odmienny obiekt w Pythonie nie zawiera odniesień do swoich nazw. Wyobraź sobie, że każda liczba całkowita, każda dykta, każda lista, każda wartość logiczna musiałaby utrzymywać listę łańcuchów reprezentujących nazwy, które się do niej odnoszą! Byłby to koszmar implementacyjny, z niewielką korzyścią dla programisty.
źródło
__name__
zawsze można ją zmodyfikować, co oznacza, że nazwa „kanoniczna” może nie być nazwą, której można użyć do pobrania obiektu (np. Podczas dynamicznego tworzenia klas).Nawet jeśli wartości zmiennych nie wskazują z powrotem na nazwę, masz dostęp do listy każdej przypisanej zmiennej i jej wartości, więc jestem zdumiony, że tylko jedna osoba zasugerowała przeglądanie tam w celu wyszukania nazwy twojej zmiennej.
Ktoś wspomniał w tej odpowiedzi, że być może będziesz musiał przejść stos i sprawdzić lokalne i globalne wszystkich, aby znaleźć
foo
, ale jeślifoo
jest przypisany w zakresie, w którym wywołujesz tęretrieve_name
funkcję, możesz użyćinspect
s,current frame
aby uzyskać wszystkie te zmienne lokalne .Moje wyjaśnienie może być trochę zbyt rozwlekłe (może powinienem był użyć "foo" mniej słów), ale oto jak będzie wyglądać w kodzie ( zwróć uwagę, że jeśli jest więcej niż jedna zmienna przypisana do tej samej wartości, pobierz obie te nazwy zmiennych ):
Jeśli wywołujesz tę funkcję z innej funkcji, na przykład:
I chcesz
baz
zamiast tegobar
, wystarczy cofnąć się o jeden zakres dalej. Można to zrobić, dodając dodatkowy element.f_back
podczascaller_local_vars
inicjalizacji.Zobacz przykład tutaj: ideone
źródło
import hooks
,ironpython
ijython
a, b = 2, 2
,retrieve_name(a)
iretrieve_name(b)
będzie zarówno zwrot['a', 'b']
lub['b', 'a']
true
dois
porównaniadef foo(bar): retrieve_name(bar)
zawsze zwróci pasek, ale co jeśli chceszfoo(baz)
zwrócićbaz
) zamiastbar
?callers_local_vars
aby cofnąć się o jeden zakres, aby spojrzał na zakres tego, co wywołujefoo
. Zmień linię nainspect.currentframe().f_back.f_back.f_locals.items()
(zwróć uwagę na dodatekf_back
).W Pythonie 3.8 można po prostu użyć funkcji debugowania f-stringów:
źródło
f'{foo=}'.split('=')[0].split('.')[-1]
W python3 ta funkcja uzyska najbardziej zewnętrzną nazwę na stosie:
Przydaje się w dowolnym miejscu kodu. Przechodzi przez odwrócony stos w poszukiwaniu pierwszego dopasowania.
źródło
retrieve_name(SomeClass.some_attribute)
to nie działa. Czy możesz w tym pomóc?stop_on_error
Nie wierzę, że to jest możliwe. Rozważmy następujący przykład:
a
Ib
punkt do tego samego obiektu, ale obiekt nie może wiedzieć, co zmienne wskazują na niego.źródło
Jest używany w ten sposób:
źródło
name(variable=variable)
wyjścia będzie['variable']
, a przy użyciuname(variable=another_variable)
będzie nie wyjście['another_variable']
, ale raczej['variable']
.>>> a = []
>>> b = a
>>> name(a=b)
['a']
>>> name(b=a)
['b']
`Oto jedno podejście. Nie polecałbym tego do niczego ważnego, ponieważ będzie dość kruchy. Ale da się to zrobić.
Utwórz funkcję, która używa
inspect
modułu, aby znaleźć kod źródłowy, który ją wywołał. Następnie możesz przeanalizować kod źródłowy, aby zidentyfikować nazwy zmiennych, które chcesz pobrać. Na przykład, oto funkcja o nazwie,autodict
która pobiera listę zmiennych i zwraca słownik mapujący nazwy zmiennych na ich wartości. Na przykład:Dałby:
Sprawdzanie samego kodu źródłowego jest lepsze niż przeszukiwanie
locals()
lub,globals()
ponieważ to drugie podejście nie mówi ci, które zmienne są tymi, które chcesz.W każdym razie oto kod:
Akcja ma miejsce w wierszu z
inspect.getouterframes
, który zwraca ciąg w wywołanym kodzieautodict
.Oczywistą wadą tego rodzaju magii jest to, że przyjmuje założenia dotyczące struktury kodu źródłowego. I oczywiście to w ogóle nie zadziała, jeśli jest uruchomione wewnątrz tłumacza.
źródło
Napisałem magię pakietu, aby solidnie robić tego rodzaju magię. Możesz pisać:
i przekaż to do konstruktora dataframe. Jest to równoważne z:
źródło
Gdybyś chciał napisać własną funkcję, mógłbyś to zrobić w taki sposób, że mógłbyś sprawdzić zmienną zdefiniowaną w lokalnych, a następnie sprawdzić globalne. Jeśli nic nie zostanie znalezione, możesz porównać za pomocą id (), aby sprawdzić, czy zmienna wskazuje na to samo miejsce w pamięci.
Jeśli twoja zmienna należy do klasy, możesz użyć className. dict .keys () lub vars (self), aby sprawdzić, czy zmienna została zdefiniowana.
źródło
locals
iglobals
... i ryzykujesz błędną nazwę, jeśli tak naprawdę nie istnieje. To mnóstwo pracy, która nie przynosi żadnych korzyści.W Pythonie
def
iclass
słowa kluczowe będą wiązać określoną nazwę z definiowanym obiektem (funkcją lub klasą). Podobnie, moduły otrzymują nazwy, ponieważ są nazywane czymś specyficznym w systemie plików. We wszystkich trzech przypadkach istnieje oczywisty sposób przypisania „kanonicznej” nazwy do danego obiektu.Jednak w przypadku innych rodzajów obiektów taka nazwa kanoniczna może po prostu nie istnieć . Weźmy na przykład pod uwagę elementy listy. Elementy na liście nie są nazywane indywidualnie i jest całkowicie możliwe, że jedynym sposobem odniesienia się do nich w programie jest użycie indeksów listy na liście zawierającej. Jeśli taka lista obiektów została przekazana do twojej funkcji, prawdopodobnie nie mógłbyś przypisać znaczących identyfikatorów do wartości.
Python nie zapisuje nazwy po lewej stronie przypisania do przypisanego obiektu, ponieważ:
Na przykład funkcje zdefiniowane za pomocą
lambda
zawsze będą miały „nazwę”<lambda>
zamiast określonej nazwy funkcji.Najlepszym podejściem byłoby po prostu poproszenie dzwoniącego o przekazanie (opcjonalnej) listy nazwisk. Jeśli wpisanie
'...','...'
jest zbyt kłopotliwe, możesz zaakceptować np. Pojedynczy łańcuch zawierający listę nazw oddzielonych przecinkami (tak jaknamedtuple
robi).źródło
locals () - Zwraca słownik zawierający zmienne lokalne bieżącego zakresu. iterując przez ten słownik możemy sprawdzić klucz, który ma wartość równą zdefiniowanej zmiennej, po prostu wyodrębnienie klucza da nam tekst zmiennej w formacie łańcuchowym.
z (po drobnych zmianach) https://www.tutorialspoint.com/How-to-get-a-variable-name-as-a-string-in-Python
źródło
Myślę, że zrobienie tego w Pythonie jest tak trudne z powodu prostego faktu, że nigdy nie poznasz nazwy używanej zmiennej. Na jego przykładzie możesz więc zrobić:
Zamiast:
źródło
po prostu inny sposób na zrobienie tego w oparciu o zawartość zmiennej wejściowej:
(zwraca nazwę pierwszej zmiennej, która pasuje do zmiennej wejściowej, w przeciwnym razie None. Można ją zmodyfikować, aby uzyskać wszystkie nazwy zmiennych, które mają taką samą zawartość jak zmienna wejściowa)
źródło
Ta funkcja wypisze nazwę zmiennej wraz z jej wartością:
źródło
Mam metodę i chociaż nie jest najbardziej wydajna ... to działa! (i nie obejmuje żadnych wyszukanych modułów).
Zasadniczo porównuje swojego identyfikatora zmiennej do globalnych () identyfikatory zmiennych , a następnie zwraca nazwę użytkownika meczu.
źródło
Jeśli celem jest pomoc w śledzeniu zmiennych, możesz napisać prostą funkcję, która etykietuje zmienną i zwraca jej wartość oraz typ. Na przykład załóżmy, że i_f = 3.01 i zaokrągliłeś to do liczby całkowitej o nazwie i_n do użycia w kodzie, a następnie potrzebujesz ciągu i_s, który zostanie umieszczony w raporcie.
To drukuje do okna przy każdym wywołaniu w celu debugowania, a także dostarcza ciąg dla pisemnego raportu. Jedynym minusem jest to, że musisz dwukrotnie wpisać zmienną za każdym razem, gdy wywołujesz funkcję.
Jestem nowicjuszem w Pythonie i znalazłem ten bardzo przydatny sposób rejestrowania moich wysiłków podczas programowania i próbowania radzenia sobie ze wszystkimi obiektami w Pythonie. Jedną z wad jest to, że whatis () zawodzi, jeśli wywołuje funkcję opisaną poza procedurą, w której jest używana. Na przykład int (i_f) był prawidłowym wywołaniem funkcji tylko dlatego, że funkcja int jest znana Pythonowi. Możesz wywołać whatis () używając int (i_f ** 2), ale jeśli z jakiegoś dziwnego powodu zdecydujesz się zdefiniować funkcję o nazwie int_squared, musi ona zostać zadeklarowana wewnątrz procedury, w której użyto whatis ().
źródło
Może to mogłoby się przydać:
Funkcja przeszukuje listę identyfikatorów wartości z zakresu globalnego (przestrzeń nazw można edytować), znajduje indeks poszukiwanej / wymaganej zmiennej lub funkcji na podstawie jej identyfikatora, a następnie zwraca nazwę z listy nazw globalnych na podstawie na pozyskanym indeksie.
źródło
Poniższa metoda nie zwróci nazwy zmiennej, ale za pomocą tej metody można łatwo utworzyć ramkę danych, jeśli zmienna jest dostępna w zasięgu globalnym.
źródło
W przypadku stałych można użyć wyliczenia, które obsługuje pobieranie jego nazwy.
źródło
Próbuję uzyskać nazwę od inspect locals, ale nie może przetwarzać var like a [1], b.val. Potem przyszedł mi do głowy nowy pomysł - pobierz nazwę var z kodu i spróbuję! kod jak poniżej:
źródło
Możesz spróbować wykonać następujące czynności, aby pobrać nazwę zdefiniowanej funkcji (nie działa to jednak w przypadku funkcji wbudowanych):
źródło