Modo più semplice per creare un dizionario di variabili separate?


220

Vorrei essere in grado di ottenere il nome di una variabile come stringa, ma non so se Python abbia così tante capacità di introspezione. Qualcosa di simile a:

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

Voglio farlo perché ho un sacco di variabili che vorrei trasformare in un dizionario come:

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

Ma vorrei qualcosa di più automatico di così.

Python ha locals()e vars(), quindi immagino che ci sia un modo.


31
Dal momento che le persone sembrano confuse su ciò che viene chiesto, lo riaffermerò qui perché è una domanda interessante. Dato un array [foo, bar, baz] vuoi un dizionario come {'foo': foo, 'bar': bar, 'baz': baz} e non sai quali variabili sono presenti nell'array. quindi l'interrogante sta chiedendo come ottenere il nome di una variabile come stringa in Python. Ora spero che le persone possano navigare attraverso le terribili risposte per trovare i pochi posti in cui impari perché questa non è davvero una buona idea in Python.
Jesse Sherlock,


2
Un uso per la tecnica sarebbe quello di semplificare le chiamate di formattazione delle stringhe: '{var} {foo} {bar}'. Format (** named (var, foo, bar)), dove "named" è la funzione che restituisce il dict ( 'var': var) come descritto.
Gordon Bean,

4
Penso che questa sia in realtà una cattiva domanda perché i nomi sono mappati su oggetti, puoi avere più nomi che puntano allo stesso oggetto e non ho mai visto alcun bisogno di raggiungere l'obiettivo di invertire tale mappatura. Quindi il fatto che la risposta sbagliata sia accettata qui non ha senso: se una ricerca su Google ti ha portato qui, stai chiaramente facendo la domanda sbagliata.
Aaron Hall

1
Questa è un'ottima idea per il debug!
john ktejik,

Risposte:


48

Stai provando a farlo?

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

Esempio

>>> 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}

1
rlotun è più vicino allo "spirito" iniziale in quanto consente di scoprire il nome. Potrei usare sia la tua risposta. O forse basta usare la mia dannata mano per scrivere. Alcune cose non sono fatte per essere automatizzate ...
e-satis

7
@ e-satis: affinché @ rlotun funzioni, è necessario fornire un elenco di variabili. Se hai l'elenco di variabili, qual è il punto di "scoprire" i loro nomi?
S.Lott

4
Perché eval invece di usare esplicitamente gente del posto e globali?

1
@Roger Pate: Perché non sono riuscito a capire quale fosse il punto dell'intero esercizio.
S.Lott

242
Questa risposta non risponde alla domanda posta. Se hai l'elenco di variabili, qual è il punto di "scoprire" i loro nomi? Per evitare la duplicazione in modo che invece di print('x: ' + x)uno si possa scrivere magic_print(x)e avere lo stesso output senza scrivere due volte il nome della variabile.
Piotr Dobrogost,

130

Come già detto, questo non è proprio qualcosa che fai in Python: le variabili sono in realtà mappature dei nomi sugli oggetti.

Tuttavia , ecco un modo per provare a farlo:

 >>> 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'

14
Questa idea ha valore, ma nota che se due nomi di variabili fanno riferimento allo stesso valore (ad es. True), Potrebbe essere restituito un nome di variabile non intenzionale.
unutbu,

14
Perché id(v) == id(a)invece di v is a? Ciò non riuscirà per gli oggetti associati a più variabili, come ints, stringhe e qualsiasi tipo definito dall'utente implementato in modo simile.

Sì, v is asarebbe una scelta migliore. E sì, sicuramente pericoloso date tutte le potenziali insidie ​​che potrebbero sorgere! ;-)
rlotun

16
@ e-satis Sono sorpreso che tu non abbia contrassegnato questa risposta come la risposta in quanto concordo con il tuo commento dicendo che rlotun è più vicino allo "spirito" iniziale, poiché consente di scoprire il nome . Inoltre la risposta di S.Lott non risponde alla tua domanda ...
Piotr Dobrogost,

2
"eccessivo e pericoloso" ... e usare eval non lo è?
bug

63

Volevo farlo abbastanza. Questo hack è molto simile al suggerimento di rlotun, ma è un one-liner, che è importante per me:

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]

3
@keflavich Mi è piaciuto molto questo approccio e di tanto in tanto l'ho usato. Tuttavia non riesco a farlo funzionare all'interno delle funzioni. Immagino ci siano modi "migliori" per farlo, ma nessuno è così semplice come nbubi lo dice. Sei stato in grado di usarlo nelle funzioni keflavich? Qui è dove faccio una domanda al riguardo.
Leone,

10
Nota che in Python 3 iteritems()è sostituito daitems()
Jonathan Wheeler il

Questo non è affidabile: spam = 1; blah = 1; blah_name = [ k for k,v in locals().items() if v is blah][0]; print(blah_name)Outputspam
andreasdr

1
@andreasdr è perché spam = 1, blah = 1; assert spam is blah. La soluzione si interrompe quando si confrontano i tipi di dati primitivi.
JYun

17

Questo è un trucco. Non funzionerà su tutte le distribuzioni di implementazioni di Python (in particolare, quelle che non hanno 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}

Nota che questo hack è fragile:

make_dict(bar,
          foo)

(chiamando make_dict su 2 righe) non funzionerà.

Invece di provare a generare il dict dai valori foo e bar, sarebbe molto più Pythonic generare il dict dai nomi delle variabili di stringa 'foo'e 'bar':

dict([(name,locals()[name]) for name in ('foo','bar')])

1
+1 per l'hacking intelligente. Naturalmente, la traccia indietro è molto lenta, quindi potrebbe essere faticoso usarlo.
e-soddisf

1
+1111111 !!!! Sì, è lento, ma quando si utilizza per sostituire print("a_very_long_name: {}'.format(a_very_long_name))chi se ne frega!
dal

14

Questo non è possibile in Python, che in realtà non ha "variabili". Python ha nomi e può esserci più di un nome per lo stesso oggetto.


sì, lo so, ho reso semplice la domanda, ma mi aspettavo qualcosa di più come "get_var_tags (var) [0]".
e-soddisf

10

Penso che il mio problema aiuterà a illustrare perché questa domanda è utile e potrebbe dare un po 'più di comprensione su come rispondere. Ho scritto una piccola funzione per fare un rapido controllo della testa in linea su varie variabili nel mio codice. Fondamentalmente, elenca il nome della variabile, il tipo di dati, la dimensione e altri attributi, in modo da poter rapidamente rilevare eventuali errori che ho commesso. Il codice è semplice:

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)))

Quindi, se hai una situazione complicata di dizionario / elenco / tupla, sarebbe molto utile che l'interprete restituisca il nome della variabile che hai assegnato. Ad esempio, ecco un dizionario strano:

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'>

Non sono sicuro di averlo messo nel posto giusto, ma ho pensato che potesse aiutare. Spero di si.


Quindi, con il tuo controllo della testa, tiene conto del fatto che variabili / nomi possono puntare a cose diverse in momenti diversi nel codice? Ad esempio, myconnectionpotrebbe indicare un valore booleano in un punto, un numero intero in un altro momento e una connessione socket in un altro punto nell'esecuzione del codice ??

9

Ho scritto una funzione poco utile in base alla risposta a questa domanda. Lo sto mettendo qui nel caso fosse utile.

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)

utilizzo:

>> a = 4
>> what(a)
a = 4
>>|

6

Trovo che se hai già un elenco specifico di valori, questo è il modo descritto da @S. Lotts è il migliore; tuttavia, il modo descritto di seguito funziona bene per ottenere tutte le variabili e le classi aggiunte in tutto il codice SENZA la necessità di fornire il nome della variabile, sebbene sia possibile specificarle se lo si desidera. Il codice può essere esteso per escludere le classi.

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')

Produzione:

{'baz': 3, 'foo': 1, 'bar': 2}
{'foo': 1}
{'foo': 1, 'bar': 2}

6

In Python 3 questo è facile

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

questo stamperà:

myVariable 5


Questo è simile all'approccio di rlotun, ma un po 'più semplice
officialhops del

10
-1. Apri una nuova finestra dell'interprete e prova for v in locals().
Air

Non sono del tutto sicuro di cosa intendi?
officialhopsof

4
Questo darà un errore: RuntimeError: il dizionario ha cambiato dimensione durante l'iterazione ...
Nizar B.

2
comunque puoi farefor v in list(locals()):
Phylliida il

5

Python3. Utilizzare inspect per acquisire lo spazio dei nomi locale chiamante, quindi utilizzare le idee presentate qui. Può restituire più di una risposta, come è stato sottolineato.

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

Buona risposta, ma per me è meglio con: ... id (eval (name, None, frame.f_back.f_locals)) == ...
Emmanuel DUMAS

5

Ecco la funzione che ho creato per leggere i nomi delle variabili. È più generale e può essere utilizzato in diverse applicazioni:

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]

Per usarlo nella domanda specificata:

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

4

Nel leggere il thread, ho visto un terribile attrito. È abbastanza facile dare una risposta sbagliata, quindi lasciare che qualcuno dia la risposta corretta. Comunque, ecco quello che ho trovato.

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

I nomi sono un po 'diversi: in realtà non sono proprietà dell'oggetto e l'oggetto stesso non sa come si chiama.

Un oggetto può avere un numero qualsiasi di nomi o nessun nome.

I nomi vivono in spazi dei nomi (come uno spazio dei nomi del modulo, uno spazio dei nomi di istanza, lo spazio dei nomi locale di una funzione).

Nota: dice che l'oggetto stesso non sa come si chiama , quindi era questo l'indizio. Gli oggetti Python non sono autoreferenziali. Quindi dice: I nomi vivono negli spazi dei nomi . Abbiamo questo in TCL / TK. Quindi forse la mia risposta sarà di aiuto (ma mi ha aiutato)

    jj = 123
    print eval ("'" + str (id (jj)) + "'")
    print dir ()

166707048
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'jj']

Quindi c'è 'jj' alla fine della lista.

Riscrivi il codice come:

    jj = 123
    print eval ("'" + str (id (jj)) + "'")
    per x in dir ():
        id di stampa (eval (x))

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

Questo brutto bit di codice ID è il nome di variabile / oggetto / qualunque-tu-pedante-chiamalo.

Quindi eccolo. L'indirizzo di memoria di 'jj' è lo stesso quando lo cerchiamo direttamente, come quando lo facciamo nel dizionario cerchiamo nello spazio dei nomi globale. Sono sicuro che puoi fare una funzione per farlo. Basta ricordare in quale spazio dei nomi si trova la vostra variabile / oggetto / wypci.

QED.


6
Hai due usi folli di eval qui. Il primo è esattamente la stessa: print id(jj). Il secondo cerca semplicemente il nome e può essere fatto più facilmente con vars().
Ned Batchelder,

2

Forse sto pensando troppo a questo ...

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'

Grande! Questo è quello che stavo cercando. Grazie @ 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)

2

Ho caricato una soluzione su pypi . È un modulo che definisce un equivalente della nameoffunzione di C # .

Esegue l'iterazione attraverso le istruzioni bytecode per il frame in cui viene chiamato, ottenendo i nomi delle variabili / attributi ad esso passati. I nomi si trovano nella .argreprdi LOADistruzioni dopo il nome della funzione.


2

Ho scritto la stregoneria del pacchetto per fare questo tipo di magia in modo robusto. Tu puoi scrivere:

from sorcery import dict_of

my_dict = dict_of(foo, bar)

1

La maggior parte degli oggetti non ha un __name__ attributo . (Classi, funzioni e moduli lo fanno; altri tipi predefiniti che ne hanno uno?)

Cos'altro ti aspetteresti print(my_var.__name__)se non perprint("my_var") ? Puoi semplicemente usare direttamente la stringa?

Potresti "tagliare" un dict:

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"})

In alternativa:

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)

2
+1 ma so che quel nome non esiste, perché tutti prendono questo "qualcosa come" litteraly? La tua soluzione non risolve il problema poiché non desidero codificare il nome, inoltre farei la soluzione dict che ho già fornito nella domanda.
e-soddisf

3
@ e-satis: se semplicemente usando tutto nei locali () risolvi il tuo problema, non ho idea di cosa tu stia chiedendo. Immagino che tu stia bene con la chiamata some_func(var), quindi ho cercato di sottolineare che non è molto lontano some_func("var"), con dictslice che ti consente di ottenere la mappatura nome-valore per più variabili contemporaneamente.

1

Bene, ho incontrato la stessa esigenza qualche giorno fa e ho dovuto ottenere il nome di una variabile che puntava all'oggetto stesso.

E perché era così necessario?

In breve, stavo costruendo un plug-in per Maya . Il plug-in principale è stato creato utilizzando C ++ ma la GUI è disegnata tramite Python (in quanto non è a uso intensivo del processore). Dal momento che io non so ancora come returnvalori multipli dal plug-in tranne quello predefinito MStatus, quindi per aggiornare un dizionario in Python ho dovuto passare il nome della variabile, puntando all'oggetto che implementava la GUI e che conteneva il dizionario stesso, il plug-in e quindi usa il MGlobal::executePythonCommand()per aggiornare il dizionario dall'ambito globale di Maya .

Per fare quello che ho fatto è stato qualcosa di simile:

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

So che non è la soluzione perfetta in globalsmolti tasti potrebbe puntare allo stesso oggetto, ad esempio:

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

e che l'approccio non è thread-safe. Correggimi se sbaglio.

Almeno questo approccio ha risolto il mio problema ottenendo il nome di qualsiasi variabile nell'ambito globale che puntava all'oggetto stesso e lo passava al plug-in, come argomento, perché lo usasse internamente.

Ho provato questo su int(la classe intera primitiva) ma il problema è che queste classi primitive non vengono escluse (si prega di correggere la terminologia tecnica utilizzata se è sbagliata). Potresti reimplementare inte poi fare int = fooma a = 3non sarà mai un oggetto fooma della primitiva. Per superare ciò devi a = foo(3)andare a.name()al lavoro.


1

Con Python 2.7 e versioni successive c'è anche la comprensione del dizionario che lo rende un po 'più breve. Se possibile, userei getattr invece eval (eval is evil) come nella risposta in alto. Il Sé può essere qualsiasi oggetto che abbia il contesto a cui sei interessato. Può essere un oggetto o locals = locals () ecc.

{name: getattr(self, name) for name in ['some', 'vars', 'here]}

1

Stavo lavorando su un problema simile. @ S.Lott ha detto "Se hai l'elenco di variabili, qual è il punto di" scoprire "i loro nomi?" E la mia risposta è solo per vedere se potrebbe essere fatto e se per qualche motivo vuoi ordinare le tue variabili per tipo in elenchi. Quindi, nella mia ricerca, mi sono imbattuto in questo thread e la mia soluzione è un po 'estesa e si basa sulla soluzione @rlotun. Un'altra cosa, ha detto @unutbu, "Questa idea ha valore, ma nota che se due nomi di variabili fanno riferimento allo stesso valore (ad esempio True), potrebbe essere restituito un nome di variabile non intenzionale." In questo esercizio che era vero così ho affrontato con esso utilizzando la comprensione elenco simile a questo per ogni eventualità: isClass = [i for i in isClass if i != 'item']. Senza di essa "item" verrebbe visualizzato in ogni elenco.

__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 []
'''

Il problema che vorrei affrontare è che i nomi non sono proprietà degli oggetti. Un singolo oggetto può avere più nomi o nessun nome. Ad esempio, hai aggiunto pi = pieal tuo codice, otterrai una voce aggiuntiva nel tuo isFloatelenco. Se hai aggiunto tuple_1[0]al tuo mixedDataTypeselenco, non verrà trovato alcun nome per esso nonostante "uno" sia nel tuo codice due volte (anche se grazie all'internet delle stringhe, entrambi saranno riferimenti allo stesso oggetto).
Blckknght,

1
@Blckknght --- Sono d'accordo. Questo è solo un altro modo di fare qualcosa che in realtà non doveva essere fatto. Non ho detto che rende risultati unici o che è infallibile. Nel fare ciò, ho scoperto che l'uso di pie ecome variabili ha causato output indesiderati e questo perché entrambi fanno parte della mathlibreria. Per me questo è stato solo un esercizio per vedere se potesse essere fatto anche se il risultato finale non è perfetto. Nel mio apprendimento di questa lingua, passare attraverso i libri va solo così lontano. Secondo me, se vuoi davvero imparare la lingua, allora devi giocare "what if" e vedere cosa ti viene in mente.
Michael Swartz,

1

puoi usare 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

un altro esempio:

>>> d = EasyDict(log=False)
>>> d.debug = True
>>> d.items()
[('debug', True), ('log', False)]

1

Su python3, questa funzione otterrà il nome più esterno nello stack:

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]

È utile ovunque nel codice. Attraversa lo stack inverso alla ricerca della prima partita.


0

Sebbene questa sia probabilmente una pessima idea, è sulla stessa linea della risposta di Rlotun ma restituirà il risultato corretto più spesso.

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

Lo chiami così:

bar = True
foo = False
bean = False
fooName = getVarName(lambda: foo)
print(fooName) # prints "foo"

0

dovrebbe ottenere l'elenco, quindi tornare

def get_var_name(**kwargs):
    """get variable name
        get_var_name(var = var)
    Returns:
        [str] -- var name
    """
    return list(kwargs.keys())[0]

0

Non restituirà il nome della variabile ma è possibile creare facilmente un dizionario dalla variabile globale.

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}

0

Con python-varnamete puoi farlo facilmente:

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}

Disclaimer: sono l'autore di quella libreria vary-python.


-1
>>> a = 1
>>> b = 1
>>> id(a)
34120408
>>> id(b)
34120408
>>> a is b
True
>>> id(a) == id(b)
True

in questo modo ottenere varname per a forse 'a' o 'b'.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.