Prostszy sposób na stworzenie słownika oddzielnych zmiennych?

220

Chciałbym móc uzyskać nazwę zmiennej jako ciąg, ale nie wiem, czy Python ma tak wiele możliwości introspekcji. Coś jak:

>>> print(my_var.__name__)
'my_var'

Chcę to zrobić, ponieważ mam kilka zmiennych, które chciałbym przekształcić w słownik, np .:

bar = True
foo = False
>>> my_dict = dict(bar=bar, foo=foo)
>>> print my_dict 
{'foo': False, 'bar': True}

Ale chciałbym coś bardziej automatycznego niż to.

Python ma locals()i vars(), więc myślę, że jest sposób.

e-satis
źródło
31
Ponieważ ludzie zdają się być zdezorientowani tym, o co proszono, powtórzę to tutaj, ponieważ jest to interesujące pytanie. Biorąc pod uwagę tablicę [foo, bar, baz], potrzebujesz słownika takiego jak {'foo': foo, 'bar': bar, 'baz': baz} i nie wiesz, jakie zmienne są w tablicy. więc pytający pyta, jak uzyskać nazwę zmiennej jako ciąg znaków w pythonie. Teraz mam nadzieję, że ludzie będą mogli przeglądać okropne odpowiedzi, aby znaleźć kilka miejsc, w których dowiesz się, dlaczego tak naprawdę nie jest to dobry pomysł w pythonie.
Jesse Sherlock
3
Możliwy duplikat: stackoverflow.com/questions/544919/...
Anderson Green
2
Jednym z zastosowań techniki byłoby usprawnienie wywołań formatowania ciągów: „{var} {foo} {bar}”. Format (** o nazwie (var, foo, bar)), gdzie „nazwa” to funkcja zwracająca dict ( „var”: var) zgodnie z opisem.
Gordon Bean
4
Myślę, że to jest złe pytanie, ponieważ nazwy są odwzorowane na obiekty, możesz mieć wiele nazw wskazujących na ten sam obiekt i nigdy nie widziałem potrzeby osiągnięcia celu odwrócenia tego odwzorowania. Więc fakt, że zła odpowiedź jest tutaj przyjęta, nie ma znaczenia - jeśli przywiodło Cię wyszukiwanie w Google, wyraźnie zadajesz złe pytanie.
Aaron Hall
1
To świetny pomysł na debugowanie!
john ktejik,

Odpowiedzi:

48

Próbujesz to zrobić?

dict( (name,eval(name)) for name in ['some','list','of','vars'] )

Przykład

>>> some= 1
>>> list= 2
>>> of= 3
>>> vars= 4
>>> dict( (name,eval(name)) for name in ['some','list','of','vars'] )
{'list': 2, 'some': 1, 'vars': 4, 'of': 3}
S.Lott
źródło
1
rlotun jest bliżej początkowego „ducha” jego, ponieważ pozwala odkryć nazwę. Mogę użyć obu twoich odpowiedzi. A może po prostu użyj mojej cholernej ręki do pisania. Niektóre rzeczy po prostu nie są tak zautomatyzowane ...
e-satis
7
@ e-satis: Aby @ rlotun działał, musisz podać listę zmiennych. Jeśli masz listę zmiennych, po co „odkrywać” ich nazwy?
S.Lott,
4
Dlaczego ewaluacja zamiast jawnego używania lokalnych i globalnych?
1
@Roger Pate: Ponieważ nie mogłem zrozumieć, o co chodzi w tym ćwiczeniu.
S.Lott,
242
Ta odpowiedź nie odpowiada na zadane pytanie. Jeśli masz listę zmiennych, po co „odkrywać” ich nazwy? Aby uniknąć powielania, aby zamiast print('x: ' + x)pisać magic_print(x)i mieć takie same dane wyjściowe bez dwukrotnego zapisu nazwy zmiennej.
Piotr Dobrogost
130

Jak powiedziałindind, nie jest to tak naprawdę czynność wykonywana w Pythonie - zmienne są w rzeczywistości odwzorowaniami nazw obiektów.

Jednakże , tu jest jeden sposób, aby spróbować zrobić:

 >>> a = 1
 >>> for k, v in list(locals().iteritems()):
         if v is a:
             a_as_str = k
 >>> a_as_str
 a
 >>> type(a_as_str)
 'str'
Rlotun
źródło
14
Pomysł ten ma swoje zalety, ale należy pamiętać, że jeśli dwie nazwy zmiennych odnoszą się do tej samej wartości (np. True), Wówczas może zostać zwrócona niezamierzona nazwa zmiennej.
unutbu
14
Dlaczego id(v) == id(a)zamiast v is a? Nie powiedzie się to w przypadku obiektów powiązanych z wieloma zmiennymi, takimi jak int, ciągi znaków i wszelkie podobnie zaimplementowane typy zdefiniowane przez użytkownika.
Tak, v is abyłby lepszy wybór. I tak, z pewnością niebezpieczne, biorąc pod uwagę wszystkie potencjalne pułapki, które mogą się pojawić! ;-)
rlotun
16
@ e-satis Jestem zaskoczony, że nie zaznaczyłeś tej odpowiedzi jako odpowiedzi, ponieważ zgadzam się z twoim komentarzem mówiącym, że rlotun jest bliżej początkowego „ducha”, ponieważ pozwala odkryć nazwę . Dodatkowo odpowiedź S.Lott wcale nie odpowiada na twoje pytanie ...
Piotr Dobrogost
2
„przesada i niebezpieczne” ... a używanie eval nie jest?
błąd
63

Bardzo chciałem to zrobić. Ten hack jest bardzo podobny do sugestii Rlotuna, ale jest to jedna linijka, co jest dla mnie ważne:

blah = 1
blah_name = [ k for k,v in locals().iteritems() if v is blah][0]

Python 3+

blah = 1
blah_name = [ k for k,v in locals().items() if v is blah][0]
Keflavich
źródło
3
@ keflavich Bardzo podobało mi się to podejście i od czasu do czasu z niego korzystam. Jednak nie mogę sprawić, by działał wewnątrz funkcji. Wydaje mi się, że są „lepsze” sposoby na zrobienie tego, ale żaden nie jest tak ładny i prosty, jak to ujął nbubis. Czy byłeś w stanie używać go w funkcjach Keflavich? Tutaj zadaję pytanie na ten temat.
Leo
10
Zauważ, że w Pythonie 3, iteritems()zastępuje sięitems()
Jonathan Wheeler,
To jest niewiarygodne: spam = 1; blah = 1; blah_name = [ k for k,v in locals().items() if v is blah][0]; print(blah_name)Wyjściaspam
andreasdr
1
@andreasdr to dlatego, że spam = 1, blah = 1; assert spam is blah. Rozwiązanie psuje się podczas porównywania pierwotnych typów danych.
JYun
17

To jest hack. Nie będzie działać na wszystkich dystrybucjach implementacji Pythona (w szczególności tych, które nie mają traceback.extract_stack).

import traceback

def make_dict(*expr):
    (filename,line_number,function_name,text)=traceback.extract_stack()[-2]
    begin=text.find('make_dict(')+len('make_dict(')
    end=text.find(')',begin)
    text=[name.strip() for name in text[begin:end].split(',')]
    return dict(zip(text,expr))

bar=True
foo=False
print(make_dict(bar,foo))
# {'foo': False, 'bar': True}

Pamiętaj, że ten hack jest delikatny:

make_dict(bar,
          foo)

(wywołanie make_dict na 2 liniach) nie będzie działać.

Zamiast próbować wygenerować dykta z wartości foo i barbyłoby znacznie bardziej Pythonic generowanie dykta z nazw zmiennych łańcuchowych 'foo'i 'bar':

dict([(name,locals()[name]) for name in ('foo','bar')])
unutbu
źródło
1
+1 za inteligentny hack. Oczywiście śledzenie wstecz jest bardzo powolne, więc korzystanie z niego może być powolne.
e-satis
1
+1111111 !!!! Tak, jest powolny, ale przy zastępowaniu print("a_very_long_name: {}'.format(a_very_long_name))kogo to obchodzi!
frnhr
14

Nie jest to możliwe w Pythonie, który tak naprawdę nie ma „zmiennych”. Python ma nazwy i może istnieć więcej niż jedna nazwa dla tego samego obiektu.

rozwijać
źródło
tak, wiem, uprościłem pytanie, ale spodziewałem się czegoś więcej, jak „get_var_tags (var) [0]”.
e-satis
10

Myślę, że mój problem pomoże zilustrować, dlaczego to pytanie jest przydatne, i może dać nieco więcej wglądu, jak na nie odpowiedzieć. Napisałem małą funkcję do szybkiego sprawdzania inline różnych zmiennych w moim kodzie. Zasadniczo zawiera nazwę zmiennej, typ danych, rozmiar i inne atrybuty, dzięki czemu mogę szybko wyłapać błędy, które popełniłem. Kod jest prosty:

def details(val):
  vn = val.__name__                 #  If such a thing existed
  vs = str(val)
  print("The Value of "+ str(vn) + " is " + vs)
  print("The data type of " + vn + " is " + str(type(val)))

Więc jeśli masz skomplikowaną sytuację słownik / lista / krotka, bardzo pomocne byłoby, aby interpreter zwrócił przypisaną nazwę zmiennej. Na przykład, oto dziwny słownik:

m = 'abracadabra'
mm=[]    
for n in m:
  mm.append(n)
mydic = {'first':(0,1,2,3,4,5,6),'second':mm,'third':np.arange(0.,10)}



details(mydic)

The Value of mydic is {'second': ['a', 'b', 'r', 'a', 'c', 'a', 'd', 'a', 'b', 'r', 'a'], 'third': array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9.]), 'first': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]}
The data type of mydic is <type 'dict'>

details(mydic['first'])
The Value of mydic['first'] is (0, 1, 2, 3, 4, 5, 6)]
The data type of mydic['first'] is <type 'list'>

details(mydic.keys())
The Value of mydic.keys() is ['second', 'third', 'first']
The data type of mydic.keys() is <type 'tuple'>

details(mydic['second'][0])
The Value of mydic['second'][0] is a
The data type of mydic['second'][0] is <type 'str'>

Nie jestem pewien, czy umieściłem to we właściwym miejscu, ale pomyślałem, że to może pomóc. Mam nadzieję, że tak.

TheProletariat
źródło
A zatem, jeśli sprawdzasz, czy bierze się pod uwagę fakt, że zmienne / nazwy mogą wskazywać na różne rzeczy w różnych momentach w kodzie? Na przykład myconnectionmoże wskazywać wartość logiczną w jednym punkcie, liczbę całkowitą w innym czasie i połączenie gniazda w innym punkcie podczas wykonywania kodu?
9

Napisałem schludną, mało przydatną funkcję opartą na odpowiedzi na to pytanie. Kładę go tutaj, na wypadek, gdyby był użyteczny.

def what(obj, callingLocals=locals()):
    """
    quick function to print name of input and value. 
    If not for the default-Valued callingLocals, the function would always
    get the name as "obj", which is not what I want.    
    """
    for k, v in list(callingLocals.items()):
         if v is obj:
            name = k
    print(name, "=", obj)

stosowanie:

>> a = 4
>> what(a)
a = 4
>>|
aquirdturtle
źródło
6

Uważam, że jeśli masz już konkretną listę wartości, to sposób opisany przez @S. Lotts jest najlepszy; jednak sposób opisany poniżej działa dobrze, aby uzyskać wszystkie zmienne i klasy dodane w całym kodzie, BEZ potrzeby podawania nazwy zmiennej, choć można je podać, jeśli chcesz. Kod można rozszerzyć, aby wykluczyć klasy.

import types
import math  # mainly showing that you could import what you will before d

# Everything after this counts
d = dict(globals())

def kv_test(k,v):
    return (k not in d and 
            k not in ['d','args'] and
            type(v) is not types.FunctionType)

def magic_print(*args):
    if len(args) == 0: 
        return {k:v for k,v in globals().iteritems() if kv_test(k,v)}
    else:
        return {k:v for k,v in magic_print().iteritems() if k in args}

if __name__ == '__main__':
    foo = 1
    bar = 2
    baz = 3
    print magic_print()
    print magic_print('foo')
    print magic_print('foo','bar')

Wynik:

{'baz': 3, 'foo': 1, 'bar': 2}
{'foo': 1}
{'foo': 1, 'bar': 2}
cdhagmann
źródło
6

W Pythonie 3 jest to łatwe

myVariable = 5
for v in locals():
  if id(v) == id("myVariable"):
    print(v, locals()[v])

to wydrukuje:

myVariable 5

oficjalny
źródło
Jest to podobne do podejścia Rlotun, ale nieco prostsze
oficjalny
10
-1. Otwórz nowe okno tłumacza i spróbuj for v in locals().
Air
Nie jestem do końca pewien, co masz na myśli?
oficjalny
4
To da błąd: RuntimeError: słownik zmienił rozmiar podczas iteracji ...
Nizar B.
2
jednak możesz to zrobićfor v in list(locals()):
Phylliida,
5

Python3. Użyj inspekcji, aby uchwycić wywoływaną lokalną przestrzeń nazw, a następnie skorzystaj z pomysłów przedstawionych tutaj. Może zwrócić więcej niż jedną odpowiedź, jak wskazano.

def varname(var):
  import inspect
  frame = inspect.currentframe()
  var_id = id(var)
  for name in frame.f_back.f_locals.keys():
    try:
      if id(eval(name)) == var_id:
        return(name)
    except:
      pass
vvxxii
źródło
Dobra odpowiedź, ale dla mnie lepiej z: ... id (eval (name, None, frame.f_back.f_locals)) == ...
Emmanuel DUMAS
5

Oto funkcja, którą utworzyłem, aby odczytać nazwy zmiennych. Jest bardziej ogólny i może być używany w różnych aplikacjach:

def get_variable_name(*variable):
    '''gets string of variable name
    inputs
        variable (str)
    returns
        string
    '''
    if len(variable) != 1:
        raise Exception('len of variables inputed must be 1')
    try:
        return [k for k, v in locals().items() if v is variable[0]][0]
    except:
        return [k for k, v in globals().items() if v is variable[0]][0]

Aby użyć go w określonym pytaniu:

>>> foo = False
>>> bar = True
>>> my_dict = {get_variable_name(foo):foo, 
               get_variable_name(bar):bar}
>>> my_dict
{'bar': True, 'foo': False}
Ania
źródło
4

Czytając wątek, zobaczyłem straszne tarcie. Łatwo jest dać złą odpowiedź, a następnie pozwolić komuś udzielić poprawnej odpowiedzi. W każdym razie oto, co znalazłem.

From: [effbot.org] ( http://effbot.org/zone/python-objects.htm#names )

Nazwy są nieco inne - nie są tak naprawdę właściwościami obiektu, a sam obiekt nie wie, jak się nazywa.

Obiekt może mieć dowolną liczbę nazw lub w ogóle żadnej nazwy.

Nazwy znajdują się w przestrzeniach nazw (takich jak przestrzeń nazw modułów, przestrzeń nazw instancji, lokalna przestrzeń nazw funkcji).

Uwaga: że mówi, że sam obiekt nie wie, jak się nazywa , więc taka była wskazówka. Obiekty Python nie są samoreferencyjne. Potem mówi: Nazwy żyją w przestrzeniach nazw . Mamy to w TCL / TK. Więc może moja odpowiedź pomoże (ale pomogła mi)

    jj = 123
    print eval („” „+ str (id (jj)) + +” ”)
    print dir ()

166707048
[„__builtins__”, „__doc__”, „__file__”, „__name__”, „__package__”, „jj”]

Na końcu listy znajduje się „jj”.

Przepisz kod jako:

    jj = 123
    print eval („” „+ str (id (jj)) + +” ”)
    dla x w dir ():
        print id (eval (x))

161922920
[„__builtins__”, „__doc__”, „__file__”, „__name__”, „__package__”, „jj”]
3077447796
136515736
3077408320
3077656800
136515736
161922920

Ten paskudny identyfikator kodu to nazwa zmiennej / object / what-you-pedantics-call-it.

Tak więc jest. Adres pamięci „jj” jest taki sam, gdy szukamy go bezpośrednio, podobnie jak podczas wyszukiwania słownika w globalnej przestrzeni nazw. Jestem pewien, że możesz to zrobić. Pamiętaj tylko, w której przestrzeni nazw znajduje się Twoja zmienna / obiekt / wypci.

CO BYŁO DO OKAZANIA.

Jesse Monroy Jr.
źródło
6
Masz tutaj dwa szalone zastosowania eval. Pierwszym z nich jest dokładnie taka sama, jak: print id(jj). Drugi po prostu sprawdza nazwę i można to zrobić łatwiej vars().
Ned Batchelder,
2

Może zastanawiam się nad tym, ale ...

str_l = next((k for k,v in locals().items() if id(l) == id(v)))


>>> bar = True
>>> foo = False
>>> my_dict=dict(bar=bar, foo=foo)
>>> next((k for k,v in locals().items() if id(bar) == id(v)))
'bar'
>>> next((k for k,v in locals().items() if id(foo) == id(v)))
'foo'
>>> next((k for k,v in locals().items() if id(my_dict) == id(v)))
'my_dict'
rh0dium
źródło
Wspaniały! Właśnie tego szukałem. Dzięki @ rh0dium ... \ nvariable = 1 \n [k for k,v in locals().items() if id(variable) == id(v)] \n Out[14]: ['variable']
Majdi
2
import re
import traceback

pattren = re.compile(r'[\W+\w+]*get_variable_name\((\w+)\)')
def get_variable_name(x):
    return pattren.match( traceback.extract_stack(limit=2)[0][3]) .group(1)

a = 1
b = a
c = b
print get_variable_name(a)
print get_variable_name(b)
print get_variable_name(c)
Xmduhan
źródło
2

Przesłałem rozwiązanie do pypi . Jest to moduł definiujący odpowiednik funkcji C # nameof.

Iteruje poprzez instrukcje kodu bajtowego dla ramki, do której jest wywoływany, i przekazuje do niego nazwy zmiennych / atrybutów. Nazwiska znajdują się w .argreprz LOADinstrukcją po nazwie funkcji.


źródło
2

Napisałem paczkę czarów, aby solidnie wykonywać tego rodzaju magię. Możesz pisać:

from sorcery import dict_of

my_dict = dict_of(foo, bar)
Alex Hall
źródło
1

Większość obiektów nie ma __name__ atrybutu . (Czy mają to klasy, funkcje i moduły; czy są jeszcze jakieś wbudowane typy, które je mają?)

Co jeszcze można się spodziewać za print(my_var.__name__)inne niżprint("my_var") ? Czy możesz po prostu użyć łańcucha bezpośrednio?

Możesz „pokroić” dyktandę:

def dict_slice(D, keys, default=None):
  return dict((k, D.get(k, default)) for k in keys)

print dict_slice(locals(), ["foo", "bar"])
# or use set literal syntax if you have a recent enough version:
print dict_slice(locals(), {"foo", "bar"})

Alternatywnie:

throw = object()  # sentinel
def dict_slice(D, keys, default=throw):
  def get(k):
    v = D.get(k, throw)
    if v is not throw:
      return v
    if default is throw:
      raise KeyError(k)
    return default
  return dict((k, get(k)) for k in keys)

źródło
2
+1, ale wiem, że ta nazwa nie istnieje, dlaczego wszyscy przyjmują to „coś w rodzaju” literatury? Twoje rozwiązanie nie rozwiązuje problemu, ponieważ nie chcę kodować nazwy, w przeciwnym razie zrobiłbym rozwiązanie dict, które już podałem w pytaniu.
e-satis
3
@ e-satis: Jeśli zwykłe użycie wszystkiego w locals () rozwiązuje problem, nie mam pojęcia, o co pytasz. Zgaduję, że nie masz some_func(var)nic przeciwko wywoływaniu , więc starałem się wskazać, że nie jest bardzo daleko some_func("var"), a dictslice pozwala uzyskać mapowanie nazwy i wartości dla wielu zmiennych jednocześnie.
1

Cóż, spotkałem się z tą samą potrzebą kilka dni temu i musiałem uzyskać nazwę zmiennej, która wskazywała na sam obiekt .

I dlaczego było to konieczne?

Krótko mówiąc, budowałem wtyczkę dla Mayi . Podstawowa wtyczka została zbudowana przy użyciu C ++, ale GUI jest pobierany przez Python (ponieważ nie wymaga dużego procesora). Ponieważ do tej pory nie wiem jak returnwiele wartości z wtyczki oprócz domyślnej MStatus, dlatego aby zaktualizować słownik w Pythonie, musiałem przekazać nazwę zmiennej, wskazując na obiekt implementujący GUI i który zawierał sam słownik do wtyczki, a następnie używał MGlobal::executePythonCommand()do aktualizacji słownika z globalnego zasięgu Maya .

Aby to zrobić, zrobiłem coś takiego:

import time

class foo(bar):

    def __init__(self):
        super(foo, self).__init__()
        self.time = time.time() #almost guaranteed to be unique on a single computer

    def name(self):
        g = globals()
        for x in g:
            if isinstance(g[x], type(self)):
                if g[x].time == self.time:
                    return x
                    #or you could:
                    #return filter(None,[x if g[x].time == self.time else None for x in g if isinstance(g[x], type(self))])
                    #and return all keys pointing to object itself

Wiem, że nie jest to idealne rozwiązanie w globals wiele kluczy może wskazywać na ten sam obiekt, np .:

a = foo()
b = a
b.name()
>>>b
or
>>>a

i że podejście nie jest bezpieczne dla wątków. Popraw mnie, jeśli się mylę.

Przynajmniej to podejście rozwiązało mój problem, uzyskując nazwę dowolnej zmiennej w zasięgu globalnym, która wskazywała na obiekt sam i przekazała go do wtyczki, jako argument, do użycia wewnętrznego.

Próbowałem tego int(prymitywna klasa całkowita), ale problem polega na tym, że te prymitywne klasy nie są pomijane (proszę poprawić używaną terminologię techniczną, jeśli jest niepoprawna). Mógłbyś ponownie wdrożyć, inta następnie zrobić, int = fooale a = 3nigdy nie będzie to obiekt foopierwotny. Aby przezwyciężyć to, musisz a = foo(3)iść a.name()do pracy.

Krwawiące palce
źródło
1

W Pythonie 2.7 i nowszych dostępne jest również rozumienie słownika, co czyni go nieco krótszym. Jeśli to możliwe, użyłbym getattr zamiast eval (eval jest zły) jak w najwyższej odpowiedzi. Jaźń może być dowolnym przedmiotem, na który patrzysz w kontekście. Może to być obiekt lub locals = locals () itp.

{name: getattr(self, name) for name in ['some', 'vars', 'here]}
yvess
źródło
1

Pracowałem nad podobnym problemem. @ S.Lott powiedział: „Jeśli masz listę zmiennych, to po co„ odkrywać ”ich nazwy?” A moja odpowiedź brzmi: czy można to zrobić i czy z jakiegoś powodu chcesz posortować zmienne według typu na listy. Tak czy inaczej, w moich badaniach natknąłem się na ten wątek, a moje rozwiązanie jest nieco rozszerzone i opiera się na rozwiązaniu @rlotun. Jedna inna rzecz, @unutbu powiedział: „Ten pomysł ma swoją wartość, ale zauważ, że jeśli dwie nazwy zmiennych odnoszą się do tej samej wartości (np. True), wówczas może zostać zwrócona niezamierzona nazwa zmiennej”. W tym ćwiczeniu to prawda więc do czynienia z nim za pomocą wyrażeń listowych podobny do tego dla każdej możliwości: isClass = [i for i in isClass if i != 'item']. Bez tego „item” pojawiłby się na każdej liście.

__metaclass__ = type

from types import *

class Class_1: pass
class Class_2: pass
list_1 = [1, 2, 3]
list_2 = ['dog', 'cat', 'bird']
tuple_1 = ('one', 'two', 'three')
tuple_2 = (1000, 2000, 3000)
dict_1 = {'one': 1, 'two': 2, 'three': 3}
dict_2 = {'dog': 'collie', 'cat': 'calico', 'bird': 'robin'}
x = 23
y = 29
pie = 3.14159
eee = 2.71828
house = 'single story'
cabin = 'cozy'

isClass = []; isList = []; isTuple = []; isDict = []; isInt = []; isFloat = []; isString = []; other = []

mixedDataTypes = [Class_1, list_1, tuple_1, dict_1, x, pie, house, Class_2, list_2, tuple_2, dict_2, y, eee, cabin]

print '\nMIXED_DATA_TYPES total count:', len(mixedDataTypes)

for item in mixedDataTypes:
    try:
        # if isinstance(item, ClassType): # use this for old class types (before 3.0)
        if isinstance(item, type):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isClass.append(mapping_as_str)
            isClass = [i for i in isClass if i != 'item']

        elif isinstance(item, ListType):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isList.append(mapping_as_str)
            isList = [i for i in isList if i != 'item']

        elif isinstance(item, TupleType):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isTuple.append(mapping_as_str)
            isTuple = [i for i in isTuple if i != 'item']

        elif isinstance(item, DictType):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isDict.append(mapping_as_str)
            isDict = [i for i in isDict if i != 'item']

        elif isinstance(item, IntType):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isInt.append(mapping_as_str)
            isInt = [i for i in isInt if i != 'item']

        elif isinstance(item, FloatType):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isFloat.append(mapping_as_str)
            isFloat = [i for i in isFloat if i != 'item']

        elif isinstance(item, StringType):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isString.append(mapping_as_str)
            isString = [i for i in isString if i != 'item']

        else:
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    other.append(mapping_as_str)
            other = [i for i in other if i != 'item']

    except (TypeError, AttributeError), e:
        print e

print '\n isClass:', len(isClass), isClass
print '  isList:', len(isList), isList
print ' isTuple:', len(isTuple), isTuple
print '  isDict:', len(isDict), isDict
print '   isInt:', len(isInt), isInt
print ' isFloat:', len(isFloat), isFloat
print 'isString:', len(isString), isString
print '   other:', len(other), other

# my output and the output I wanted
'''
MIXED_DATA_TYPES total count: 14

 isClass: 2 ['Class_1', 'Class_2']
  isList: 2 ['list_1', 'list_2']
 isTuple: 2 ['tuple_1', 'tuple_2']
  isDict: 2 ['dict_1', 'dict_2']
   isInt: 2 ['x', 'y']
 isFloat: 2 ['pie', 'eee']
isString: 2 ['house', 'cabin']
   other: 0 []
'''
Michael Swartz
źródło
Kwestią, którą podniosę, jest to, że nazwy nie są właściwościami obiektów. Pojedynczy obiekt może mieć wiele nazw lub może nie mieć żadnej nazwy. Na przykład dodałeśpi = pie do swojego kodu, uzyskasz dodatkowy wpis na isFloatliście. Jeśli dodałeś tuple_1[0]do swojej mixedDataTypeslisty, nie znajdzie się dla niej nazwy, mimo że „jeden” znajduje się w kodzie dwa razy (chociaż dzięki internowaniu łańcucha, oba będą odwołaniami do tego samego obiektu).
Blckknght
1
@Blckknght --- Zgadzam się. To tylko kolejny sposób na zrobienie czegoś, co tak naprawdę nie było do zrobienia. Nie powiedziałem, że zapewnia unikalne wyniki lub że jest nieomylny. Robiąc to, dowiedziałem się, że używanie pii ejako zmiennych powodowało niechciane dane wyjściowe, a to dlatego, że oba są częścią mathbiblioteki. Dla mnie było to tylko ćwiczenie, aby sprawdzić, czy da się to zrobić, nawet jeśli efekt końcowy nie jest idealny. W mojej nauce tego języka przeglądanie książek idzie tylko tak daleko. Moim zdaniem, jeśli naprawdę chcesz nauczyć się języka, musisz zagrać „co jeśli” i zobaczyć, co wymyślisz.
Michael Swartz,
1

możesz użyć easydict

>>> from easydict import EasyDict as edict
>>> d = edict({'foo':3, 'bar':{'x':1, 'y':2}})
>>> d.foo
3
>>> d.bar.x
1
>>> d = edict(foo=3)
>>> d.foo
3

inny przykład:

>>> d = EasyDict(log=False)
>>> d.debug = True
>>> d.items()
[('debug', True), ('log', False)]
Eli
źródło
1

W Python3 ta funkcja otrzyma najbardziej zewnętrzną nazwę ze stosu:

import inspect


def retrieve_name(var):
        """
        Gets the name of var. Does it from the out most frame inner-wards.
        :param var: variable to get name from.
        :return: string
        """
        for fi in reversed(inspect.stack()):
            names = [var_name for var_name, var_val in fi.frame.f_locals.items() if var_val is var]
            if len(names) > 0:
                return names[0]

Jest przydatny w dowolnym miejscu kodu. Przemierza odwrócony stos w poszukiwaniu pierwszego dopasowania.

juan Isaza
źródło
0

Chociaż jest to prawdopodobnie okropny pomysł, jest zgodny z odpowiedzią rlotun, ale częściej zwraca poprawny wynik.

import inspect
def getVarName(getvar):
  frame = inspect.currentframe()
  callerLocals = frame.f_back.f_locals
  for k, v in list(callerLocals.items()):
    if v is getvar():
      callerLocals.pop(k)
      try:
        getvar()
        callerLocals[k] = v
      except NameError:
        callerLocals[k] = v
        del frame
        return k
  del frame

Nazywasz to tak:

bar = True
foo = False
bean = False
fooName = getVarName(lambda: foo)
print(fooName) # prints "foo"
Phylliida
źródło
0

powinien dostać listę, a następnie wrócić

def get_var_name(**kwargs):
    """get variable name
        get_var_name(var = var)
    Returns:
        [str] -- var name
    """
    return list(kwargs.keys())[0]
Paul
źródło
0

Nie zwróci nazwy zmiennej, ale możesz łatwo utworzyć słownik ze zmiennej globalnej.

class CustomDict(dict):
    def __add__(self, other):
        return CustomDict({**self, **other})

class GlobalBase(type):
    def __getattr__(cls, key):
        return CustomDict({key: globals()[key]})

    def __getitem__(cls, keys):
        return CustomDict({key: globals()[key] for key in keys})

class G(metaclass=GlobalBase):
    pass

x, y, z = 0, 1, 2

print('method 1:', G['x', 'y', 'z']) # Outcome: method 1: {'x': 0, 'y': 1, 'z': 2}
print('method 2:', G.x + G.y + G.z) # Outcome: method 2: {'x': 0, 'y': 1, 'z': 2}
użytkownik5828964
źródło
0

Z python-varnamełatwością możesz to zrobić:

pip install python-varname

from varname import Wrapper

foo = Wrapper(True)
bar = Wrapper(False)

your_dict = {val.name: val.value for val in (foo, bar)}

print(your_dict)

# {'foo': True, 'bar': False}

Oświadczenie: Jestem autorem tej biblioteki zmiennych python-varname.

Panwen Wang
źródło
-1
>>> a = 1
>>> b = 1
>>> id(a)
34120408
>>> id(b)
34120408
>>> a is b
True
>>> id(a) == id(b)
True

w ten sposób uzyskaj zmienną dla nazwy „a” lub „b”.

su dazhuang
źródło