Einfachere Möglichkeit, ein Wörterbuch mit separaten Variablen zu erstellen?

220

Ich möchte den Namen einer Variablen als Zeichenfolge abrufen können, weiß aber nicht, ob Python über so viele Introspektionsfunktionen verfügt. Etwas wie:

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

Ich möchte das tun, weil ich eine Reihe von Variablen habe, die ich in ein Wörterbuch verwandeln möchte, wie:

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

Aber ich hätte gerne etwas Automatischeres.

Python haben locals()und vars(), also denke ich, gibt es einen Weg.

e-satis
quelle
31
Da die Leute verwirrt zu sein scheinen, was gefragt wird, werde ich es hier wiederholen, weil es eine interessante Frage ist. Bei einem gegebenen Array [foo, bar, baz] möchten Sie ein Wörterbuch wie {'foo': foo, 'bar': bar, 'baz': baz} und Sie wissen nicht, welche Variablen im Array enthalten sind. Der Fragesteller fragt also, wie Sie den Namen einer Variablen als Zeichenfolge in Python erhalten. Jetzt können die Leute hoffentlich durch die schrecklichen Antworten navigieren, um die wenigen Stellen zu finden, an denen Sie erfahren, warum dies in Python keine wirklich gute Idee ist.
Jesse Sherlock
3
Mögliches Duplikat: stackoverflow.com/questions/544919/…
Anderson Green
2
Eine Verwendung für die Technik besteht darin, Aufrufe zur Formatierung von Zeichenfolgen zu optimieren: '{var} {foo} {bar}'. Format (** benannt (var, foo, bar)), wobei "benannt" die Funktion ist, die das Diktat zurückgibt ( 'var': var) wie beschrieben.
Gordon Bean
4
Ich denke, dies ist tatsächlich eine schlechte Frage, da Namen Objekten zugeordnet sind, mehrere Namen auf dasselbe Objekt verweisen können und ich nie die Notwendigkeit gesehen habe, das Ziel der Umkehrung dieser Zuordnung zu erreichen. Die Tatsache, dass hier die falsche Antwort akzeptiert wird, ist bedeutungslos. Wenn Sie durch eine Google-Suche hierher gebracht wurden, stellen Sie eindeutig die falsche Frage.
Aaron Hall
1
Dies ist eine großartige Idee zum Debuggen!
John Ktejik

Antworten:

48

Versuchst du das zu tun?

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

Beispiel

>>> 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
quelle
1
rlotun ist dem anfänglichen "Geist" näher, da es erlaubt, den Namen zu entdecken. Ich werde beide Ihre Antwort benutzen. Oder benutze einfach meine verdammte Hand zum Tippen. Einige Dinge sind einfach nicht so automatisiert ...
e-satis
7
@ e-satis: Damit @ rlotun funktioniert, müssen Sie die Liste der Variablen angeben. Wenn Sie die Liste der Variablen haben, was bringt es, ihre Namen zu "entdecken"?
S.Lott
4
Warum auswerten, anstatt explizit Einheimische und Globale zu verwenden?
1
@ Roger Pate: Weil ich nicht herausfinden konnte, worum es bei der ganzen Übung ging.
S.Lott
242
Diese Antwort beantwortet die gestellte Frage nicht. Wenn Sie die Liste der Variablen haben, was bringt es, ihre Namen zu "entdecken"? Um Doppelarbeit zu vermeiden, kann man stattdessen print('x: ' + x)schreiben magic_print(x)und dieselbe Ausgabe haben, ohne den Namen der Variablen zweimal zu schreiben.
Piotr Dobrogost
130

Wie bereits erwähnt, ist dies in Python nicht wirklich der Fall - Variablen sind tatsächlich Namenszuordnungen zu Objekten.

Allerdings , hier ist eine Möglichkeit , es zu versuchen und zu tun:

 >>> 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
quelle
14
Diese Idee hat ihre Berechtigung. Beachten Sie jedoch, dass Truemöglicherweise ein unbeabsichtigter Variablenname zurückgegeben wird , wenn zwei Variablennamen auf denselben Wert verweisen (z. B. ).
Unutbu
14
Warum id(v) == id(a)statt v is a? Dies schlägt bei Objekten fehl, die an mehrere Variablen gebunden sind, z. B. Ints, Strings und ähnlich implementierte benutzerdefinierte Typen.
Ja, v is awäre eine bessere Wahl. Und ja, sicherlich gefährlich angesichts aller möglichen Fallstricke! ;-)
rlotun
16
@ e-satis Ich bin überrascht, dass Sie diese Antwort nicht als Antwort markiert haben, da ich Ihrem Kommentar zustimme, dass rlotun dem ursprünglichen "Geist" näher kommt, da es ermöglicht, den Namen zu entdecken . Außerdem beantwortet S.Lotts Antwort Ihre Frage überhaupt nicht ...
Piotr Dobrogost
2
"übertrieben und gefährlich" ... und eval nicht?
Fehler
63

Ich wollte das schon ziemlich oft machen. Dieser Hack ist dem Vorschlag von rlotun sehr ähnlich, aber es ist ein Einzeiler, was mir wichtig ist:

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
quelle
3
@keflavich Ich mochte diesen Ansatz sehr und habe ihn jetzt von Zeit zu Zeit verwendet. Ich kann es jedoch nicht dazu bringen, innerhalb von Funktionen zu funktionieren. Ich denke, es gibt "bessere" Möglichkeiten, dies zu tun, aber keine ist so einfach und nett wie nbubis es ausdrückt. Konnten Sie es in Funktionen keflavich verwenden? Hier stelle ich eine Frage dazu.
Leo
10
Beachten Sie, dass in Python 3 iteritems()durchitems()
Jonathan Wheeler
Dies ist unzuverlässig: spam = 1; blah = 1; blah_name = [ k for k,v in locals().items() if v is blah][0]; print(blah_name)Ausgabenspam
andreasdr
1
@andreasdr das liegt daran spam = 1, blah = 1; assert spam is blah. Die Lösung bricht beim Vergleich primitiver Datentypen ab.
JYun
17

Das ist ein Hack. Es funktioniert nicht auf allen Python-Implementierungsdistributionen (insbesondere auf solchen, die keine haben 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}

Beachten Sie, dass dieser Hack zerbrechlich ist:

make_dict(bar,
          foo)

(Aufruf von make_dict in 2 Zeilen) funktioniert nicht.

Anstatt zu versuchen, das Diktat aus den Werten foo und zu generieren bar, wäre es viel pythonischer, das Diktat aus den Namen der Zeichenfolgenvariablen zu generieren 'foo'und 'bar':

dict([(name,locals()[name]) for name in ('foo','bar')])
unutbu
quelle
1
+1 für den Smart Hack. Natürlich ist die Rückverfolgung sehr langsam, so dass es möglicherweise schwierig ist, sie zu verwenden.
E-Satis
1
+1111111 !!!! Ja, es ist langsam, aber beim Ersetzen, print("a_very_long_name: {}'.format(a_very_long_name))wen interessiert das?
Frnhr
14

Dies ist in Python nicht möglich, das wirklich keine "Variablen" hat. Python hat Namen, und es kann mehr als einen Namen für dasselbe Objekt geben.

entspannen
quelle
Ja, ich weiß, ich habe die Frage einfach gemacht, aber ich hatte eher etwas wie "get_var_tags (var) [0]" erwartet.
E-
10

Ich denke, mein Problem wird helfen, zu veranschaulichen, warum diese Frage nützlich ist, und es kann ein bisschen mehr Einblick geben, wie man sie beantwortet. Ich habe eine kleine Funktion geschrieben, um verschiedene Variablen in meinem Code schnell inline zu überprüfen. Grundsätzlich werden der Variablenname, der Datentyp, die Größe und andere Attribute aufgelistet, sodass ich Fehler, die ich gemacht habe, schnell erkennen kann. Der Code ist einfach:

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

Wenn Sie also eine komplizierte Situation mit Wörterbuch / Liste / Tupel haben, ist es sehr hilfreich, wenn der Interpreter den von Ihnen zugewiesenen Variablennamen zurückgibt. Zum Beispiel ist hier ein seltsames Wörterbuch:

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

Ich bin mir nicht sicher, ob ich das an die richtige Stelle gebracht habe, aber ich dachte, es könnte helfen. Ich hoffe es tut.

DasProletariat
quelle
Berücksichtigt dies bei Ihrer Kopfprüfung die Tatsache, dass Variablen / Namen zu unterschiedlichen Zeiten im Code auf verschiedene Dinge verweisen können? Könnte zum Beispiel myconnectionauf einen booleschen Wert an einem Punkt, eine Ganzzahl zu einem anderen Zeitpunkt und eine Socket-Verbindung an einem anderen Punkt in der Codeausführung zeigen?
9

Ich habe eine nette kleine nützliche Funktion geschrieben, die auf der Antwort auf diese Frage basiert. Ich setze es hier ein, falls es nützlich ist.

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)

Verwendung:

>> a = 4
>> what(a)
a = 4
>>|
aquirdturtle
quelle
6

Ich finde, wenn Sie bereits eine bestimmte Liste von Werten haben, ist dies der von @S beschriebene Weg. Lotts ist das Beste; jedoch die beschriebene Art und Weise unten funktioniert gut , alle Variablen und Klassen im Code hinzugefügt zu bekommen ohne die Notwendigkeit Variablennamen zur Verfügung zu stellen , obwohl Sie sie angeben können , wenn Sie wollen. Der Code kann erweitert werden, um Klassen auszuschließen.

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

Ausgabe:

{'baz': 3, 'foo': 1, 'bar': 2}
{'foo': 1}
{'foo': 1, 'bar': 2}
cdhagmann
quelle
6

In Python 3 ist dies einfach

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

Dies wird gedruckt:

myVariable 5

offizielle Hopfen von
quelle
Dies ist ähnlich wie Rlotuns Ansatz, aber ein bisschen einfacher
offizielle
10
-1. Öffnen Sie ein neues Interpreter-Fenster und versuchen Sie es for v in locals().
Luft
Ich bin mir nicht ganz sicher, was du meinst?
offizielle
4
Dies wird einen Fehler geben: RuntimeError: Wörterbuch Größe während der Iteration geändert ...
Nizar B.
2
wie auch immer Sie tun könnenfor v in list(locals()):
Phylliida
5

Python3. Verwenden Sie inspect, um den aufrufenden lokalen Namespace zu erfassen, und verwenden Sie dann die hier vorgestellten Ideen. Kann mehr als eine Antwort zurückgeben, wie bereits erwähnt wurde.

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
quelle
Gute Antwort, aber für mich ist es besser mit: ... id (eval (name, None, frame.f_back.f_locals)) == ...
Emmanuel DUMAS
5

Hier ist die Funktion, die ich zum Lesen der Variablennamen erstellt habe. Es ist allgemeiner und kann in verschiedenen Anwendungen verwendet werden:

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]

So verwenden Sie es in der angegebenen Frage:

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

Beim Lesen des Threads sah ich sehr viel Reibung. Es ist einfach genug, eine schlechte Antwort zu geben und dann jemanden die richtige Antwort geben zu lassen. Wie auch immer, hier ist was ich gefunden habe.

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

Die Namen sind etwas anders - sie sind nicht wirklich Eigenschaften des Objekts, und das Objekt selbst weiß nicht, wie es heißt.

Ein Objekt kann eine beliebige Anzahl von Namen oder überhaupt keinen Namen haben.

Namen leben in Namespaces (z. B. einem Modul-Namespace, einem Instanz-Namespace oder dem lokalen Namespace einer Funktion).

Hinweis: Das Objekt selbst weiß nicht, wie es heißt. Das war also der Hinweis. Python-Objekte sind nicht selbstreferenziell. Dann heißt es, Namen leben in Namespaces . Wir haben dies in TCL / TK. Vielleicht hilft meine Antwort (aber sie hat mir geholfen)

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

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

Am Ende der Liste steht also 'jj'.

Schreiben Sie den Code wie folgt um:

    jj = 123
    print eval ("'" + str (id (jj)) + "'")
    für x in dir ():
        Druck-ID (eval (x))

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

Dieses böse Stück Code-ID ist der Name der Variablen / des Objekts / wie auch immer-Sie-Pedantics-es nennen.

Also, da ist es. Die Speicheradresse von 'jj' ist dieselbe, wenn wir direkt danach suchen, wie wenn wir das Wörterbuch im globalen Namensraum nachschlagen. Ich bin sicher, Sie können eine Funktion dafür erstellen. Denken Sie daran, in welchem ​​Namespace sich Ihre Variable / Objekt / Wypci befindet.

QED.

Jesse Monroy Jr.
quelle
6
Sie haben hier zwei verrückte Verwendungszwecke von eval. Das erste ist genau das gleiche wie : print id(jj). Der zweite sucht einfach nach dem Namen und kann einfacher mit durchgeführt werden vars().
Ned Batchelder
2

Vielleicht überdenke ich das aber ..

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
quelle
Toll! Das habe ich gesucht. Danke @ 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
quelle
2

Ich habe eine Lösung auf pypi hochgeladen . Es ist ein Modul, das ein Äquivalent der C # nameof-Funktion definiert.

Es durchläuft Bytecode-Anweisungen für den aufgerufenen Frame und erhält die Namen der an ihn übergebenen Variablen / Attribute. Die Namen werden in der gefunden .argreprvon LOADAnweisungen folgenden Funktionsnamen.


quelle
2

Ich habe das Paket Zauberei geschrieben , um diese Art von Magie robust zu machen. Du kannst schreiben:

from sorcery import dict_of

my_dict = dict_of(foo, bar)
Alex Hall
quelle
1

Die meisten Objekte haben kein Attribut __name__ . (Klassen, Funktionen und Module tun dies; gibt es noch mehr eingebaute Typen, die einen haben?)

Was würden Sie sonst noch erwarten print(my_var.__name__)als print("my_var")? Können Sie den String einfach direkt verwenden?

Sie könnten ein Diktat "in Scheiben schneiden":

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

Alternative:

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)

quelle
2
+1 aber ich weiß, dass dieser Name nicht existiert, warum nimmt jeder dieses "so etwas wie" Wurf? Ihre Lösung löst das Problem nicht, da ich den Namen nicht harcodieren möchte. Übermäßig würde ich die Dikt-Lösung ausführen, die ich bereits in der Frage angegeben habe.
E-Satis
3
@ e-satis: Wenn die einfache Verwendung von allem in local () Ihr Problem löst, habe ich keine Ahnung, was Sie fragen. Ich vermute , Sie können mit dem Aufrufen einverstanden seinsome_func(var) , also habe ich versucht, darauf hinzuweisen, dass es nicht weit davon entfernt some_func("var")ist. Mit dictslice können Sie die Name-Wert-Zuordnung für mehrere Variablen gleichzeitig abrufen .
1

Nun, ich hatte vor ein paar Tagen genau das gleiche Bedürfnis und musste den Namen einer Variablen erhalten, die auf das Objekt selbst zeigte.

Und warum war es so notwendig?

Kurz gesagt, ich habe ein Plug-In für Maya erstellt . Das Kern-Plug-In wurde mit C ++ erstellt, aber die GUI wird über Python gezeichnet (da es nicht prozessorintensiv ist). Da ich bis jetzt nicht weiß, wie man returnWerte aus dem Plug-In mit Ausnahme der Standardeinstellung MStatusmultipliziert, musste ich zum Aktualisieren eines Wörterbuchs in Python den Namen der Variablen übergeben und auf das Objekt zeigen, das die GUI implementiert und welches enthielt das Wörterbuch selbst, in das Plug-In und verwenden Sie dann das MGlobal::executePythonCommand(), um das Wörterbuch aus dem globalen Bereich von Maya zu aktualisieren .

Das zu tun, was ich getan habe, war so etwas wie:

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

Ich weiß, dass es nicht die perfekte Lösung ist, wenn globalsviele Schlüssel auf dasselbe Objekt zeigen könnten, z.

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

und dass der Ansatz nicht threadsicher ist. Korrigieren Sie mich, wenn ich falsch liege.

Zumindest löste dieser Ansatz mein Problem, indem er den Namen einer Variablen im globalen Bereich abrief, die auf das Objekt selbst zeigte, und es als Argument an das Plug-In weitergab, damit es intern verwendet werden kann.

Ich habe dies anprobiert int(die primitive Ganzzahlklasse), aber das Problem ist, dass diese primitiven Klassen nicht umgangen werden (bitte korrigieren Sie die verwendete technische Terminologie, wenn sie falsch ist). Sie könnten neu implementieren intund dann tun int = foo, a = 3werden aber niemals ein Objekt des fooPrimitiven sein. Um das zu überwinden, muss man a = foo(3)sich a.name()an die Arbeit machen.

Blutende Finger
quelle
1

Mit Python 2.7 und neuer gibt es auch ein Wörterbuchverständnis, das es etwas kürzer macht. Wenn möglich, würde ich getattr anstelle von eval (eval ist böse) wie in der oberen Antwort verwenden. Selbst kann jedes Objekt sein, das den Kontext hat, den Sie betrachten. Es kann ein Objekt sein oder einheimische = einheimische () usw.

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

Ich habe an einem ähnlichen Problem gearbeitet. @ S.Lott sagte: "Wenn Sie die Liste der Variablen haben, was bringt es, ihre Namen zu" entdecken "?" Und meine Antwort ist nur zu sehen, ob es möglich ist und ob Sie aus irgendeinem Grund Ihre Variablen nach Typ in Listen sortieren möchten. Bei meinen Recherchen bin ich auf diesen Thread gestoßen, und meine Lösung ist etwas erweitert und basiert auf der @ rlotun-Lösung. Eine andere Sache, sagte @unutbu, "Diese Idee hat ihre Berechtigung, aber beachten Sie, dass, wenn zwei Variablennamen auf denselben Wert verweisen (z. B. True), möglicherweise ein unbeabsichtigter Variablenname zurückgegeben wird." In dieser Übung stimmte das, also habe ich mich damit befasst, indem ich für jede Möglichkeit ein ähnliches Listenverständnis verwendet habe : isClass = [i for i in isClass if i != 'item']. Ohne sie würde "item" in jeder Liste angezeigt.

__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
quelle
Das Problem, das ich damit angehen würde, ist, dass Namen keine Eigenschaften von Objekten sind. Ein einzelnes Objekt kann mehrere oder gar keine Namen haben. Wenn Sie beispielsweise pi = pieIhren Code hinzugefügt haben , erhalten Sie einen zusätzlichen Eintrag in Ihrer isFloatListe. Wenn Sie tuple_1[0]Ihrer mixedDataTypesListe hinzugefügt haben , wird kein Name dafür gefunden, obwohl "eins" zweimal in Ihrem Code enthalten ist (obwohl beide dank der internen Zeichenfolge Verweise auf dasselbe Objekt sind).
Blckknght
1
@Blckknght --- Ich stimme zu. Dies ist nur eine andere Möglichkeit, etwas zu tun, das eigentlich nicht gedacht war. Ich habe nicht gesagt, dass es einzigartige Ergebnisse liefert oder dass es unfehlbar ist. Dabei habe ich herausgefunden, dass die Verwendung von piund eals Variablen unerwünschte Ausgaben verursacht und dass beide Teil der mathBibliothek sind. Für mich war dies nur eine Übung, um zu sehen, ob dies möglich ist, obwohl das Endergebnis nicht perfekt ist. Beim Erlernen dieser Sprache geht das Durchgehen von Büchern nur so weit. Wenn Sie die Sprache wirklich lernen möchten, müssen Sie meiner Meinung nach "Was wäre wenn" spielen und sehen, was Sie sich einfallen lassen.
Michael Swartz
1

Sie können easydict verwenden

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

ein anderes Beispiel:

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

Unter python3 erhält diese Funktion den äußersten Namen im Stapel:

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]

Es ist überall im Code nützlich. Durchläuft den umgekehrten Stapel und sucht nach dem ersten Match.

Juan Isaza
quelle
0

Dies ist wahrscheinlich eine schreckliche Idee, entspricht jedoch der Antwort von rlotun, gibt jedoch häufiger das richtige Ergebnis zurück.

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

Sie nennen es so:

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

sollte Liste bekommen und dann zurückkehren

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

Der Name der Variablen wird nicht zurückgegeben, Sie können jedoch problemlos ein Wörterbuch aus einer globalen Variablen erstellen.

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}
user5828964
quelle
0

Mit können python-varnameSie es einfach tun:

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}

Haftungsausschluss: Ich bin der Autor dieser Python-Varname-Bibliothek.

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

Auf diese Weise erhalten Sie den Variablennamen für ein vielleicht 'a' oder 'b'.

su dazhuang
quelle