Python-Variablen als Schlüssel zum Diktieren

77

Gibt es eine einfachere Möglichkeit, dies in Python (2.7) zu tun?: Hinweis: Dies ist nichts Besonderes, wie das Einfügen aller lokalen Variablen in ein Wörterbuch. Nur die, die ich in einer Liste angegeben habe.

apple = 1
banana = 'f'
carrot = 3
fruitdict = {}

# I want to set the key equal to variable name, and value equal to variable value
# is there a more Pythonic way to get {'apple': 1, 'banana': 'f', 'carrot': 3}?

for x in [apple, banana, carrot]:
    fruitdict[x] = x # (Won't work)
atp
quelle
1
Können die Variablen im Diktat definiert werden? Wie Fruitdict = Dikt (Apfel = 1, Banane = 2, Karotte = 3)?
Dr. Jimbob
Nicht wirklich, es gibt viel Code für jede Variable, so dass es unlesbar wäre.
atp
Ich nehme an, Sie wissen, dass Ihr Code nicht das tut, was der Kommentar sagt? Sie können nicht rückwärts von Objekten zu Namen wechseln, es sei denn, Sie finden in einem Namespace-Wörterbuch wie local (), was Sie möchten. Sie können jedoch eine Funktion schreiben, die diese Variablen im Namespace-Wörterbuch nachschlägt und die gefundenen Werte diesem Schlüssel zuweist. siehe jimbobs antwort
Thomas
Ja, sorry, ich sollte das klarstellen.
Am

Antworten:

79
for i in ('apple', 'banana', 'carrot'):
    fruitdict[i] = locals()[i]
Dr. Jimbob
quelle
16
einzeiligdict([(i, locals()[i]) for i in ('apple', 'banana', 'carrot')])
Dinya
3
Während es sich bei dieser Frage um 2.7 handelt, beachten Sie, dass der obige Einzeiler in Python 3 nicht funktioniert, da er locals()anscheinend auf den Umfang des Listenverständnisses hinweist.
Roope
Was ist die Lösung in Python 3?
Dr_Zaszuś
@ Dr_Zaszuś, die Sie loc=locals()zuvor eingestellt haben dict([(i, loc[i]) for in ('apple', 'banana', 'carrot')]).
Bers
19

Die globals()Funktion gibt ein Wörterbuch zurück, das alle Ihre globalen Variablen enthält.

>>> apple = 1
>>> banana = 'f'
>>> carrot = 3
>>> globals()
{'carrot': 3, 'apple': 1, '__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None, 'banana': 'f'}

Es gibt auch eine ähnliche Funktion namens locals().

Mir ist klar, dass dies wahrscheinlich nicht genau das ist, was Sie wollen, aber es kann einen Einblick geben, wie Python den Zugriff auf Ihre Variablen ermöglicht.

Bearbeiten : Es hört sich so an, als ob Ihr Problem besser gelöst werden kann, indem Sie zunächst ein Wörterbuch verwenden:

fruitdict = {}
fruitdict['apple'] = 1
fruitdict['banana'] = 'f'
fruitdict['carrot'] = 3
Greg Hewgill
quelle
Entschuldigung, ich muss bearbeitet haben, nachdem Sie Ihre Antwort geschrieben haben. Ich brauche nur die Variablen , die ich angeben, nicht alle Einheimischen () oder Globals ()
atp
@Jasie: Ich habe ein Beispiel hinzugefügt, wie man einfach ein Wörterbuch verwendet, anstatt mit Variablen herumzuspielen.
Greg Hewgill
6

Ein Einzeiler ist: -

fruitdict = dict(zip(('apple','banana','carrot'), (1,'f', '3'))
Dantalion
quelle
Danke, aber die Zahlen waren zufällige Zuweisungen (brauchten keinen Bereich ()).
atp
3

Hier steht es in einer Zeile, ohne dass eine der Variablen oder ihre Werte erneut eingegeben werden muss:

fruitdict.update({k:v for k,v in locals().copy().iteritems() if k[:2] != '__' and k != 'fruitdict'})
Christian Vanderwall
quelle
2

Basierend auf der Antwort von mouad können Sie die Variablen anhand eines Präfixes pythonischer auswählen:

# All the vars that I want to get start with fruit_
fruit_apple = 1
fruit_carrot = 'f'
rotten = 666

prefix = 'fruit_'
sourcedict = locals()
fruitdict = { v[len(prefix):] : sourcedict[v]
              for v in sourcedict
              if v.startswith(prefix) }
# fruitdict = {'carrot': 'f', 'apple': 1}

Sie können dies sogar in eine Funktion mit Präfix und Sourcing-Argument als Argument einfügen.

Arnout
quelle
1

Nun, das ist ein bisschen, ähm ... nicht pythonisch ... hässlich ... hackisch ...

Hier ist ein Codeausschnitt, der davon ausgeht, dass Sie ein Wörterbuch aller lokalen Variablen erstellen möchten, die Sie erstellen, nachdem ein bestimmter Prüfpunkt erstellt wurde:

checkpoint = [ 'checkpoint' ] + locals().keys()[:]
## Various local assigments here ...
var_keys_since_checkpoint = set(locals().keys()) - set(checkpoint)
new_vars = dict()
for each in var_keys_since_checkpoint:
   new_vars[each] = locals()[each]

Beachten Sie, dass wir den 'Checkpoint'-Schlüssel explizit zu unserer Erfassung des hinzufügen. locals().keys() Ich nehme auch explizit einen Teil davon, obwohl dies in diesem Fall nicht erforderlich sein sollte, da die Referenz abgeflacht werden muss, um sie dem [' Checkpoint hinzuzufügen ' ] aufführen. Wenn Sie jedoch eine Variante dieses Codes verwenden und versuchen, die ['checkpoint'] + portion (because that key was already inlocal () , for example) ... then, without the [:] slice you could end up with a reference to thelocal (). Keys () `zu verknüpfen, deren Werte sich beim Hinzufügen von Variablen ändern würden.

Nebenbei kann ich mir keine Möglichkeit vorstellen, so etwas wie new_vars.update()mit einer Liste von Schlüsseln aufzurufen , die hinzugefügt / aktualisiert werden sollen. Die forSchleife ist also am tragbarsten. Ich nehme an, dass ein Wörterbuchverständnis in neueren Versionen von Python verwendet werden könnte. Dies scheint jedoch nichts weiter als eine Runde Code-Golf zu sein.

Jim Dennis
quelle
-1

Diese Frage wurde praktisch beantwortet, aber ich wollte nur sagen, dass es lustig war, dass Sie gesagt haben

Dies ist nichts Besonderes, wie das Einfügen aller lokalen Variablen in ein Wörterbuch.

Weil es eigentlich "schicker" ist

was Sie wollen ist:

apple = 1
banana = 'f'
carrot = 3
fruitdict = {}

# I want to set the key equal to variable name, and value equal to variable value
# is there a more Pythonic way to get {'apple': 1, 'banana': 'f', 'carrot': 3}?

names= 'apple banana carrot'.split() # I'm just being lazy for this post
items = globals()                    # or locals()

for name in names:
    fruitdict[name] = items[name]

Ehrlich gesagt, kopieren Sie nur Elemente von einem Wörterbuch in ein anderes.

(Greg Hewgill gab praktisch die ganze Antwort, ich habe sie gerade vervollständigt)

... und wie die Leute vorgeschlagen haben, sollten Sie diese wahrscheinlich zuerst in das Wörterbuch aufnehmen, aber ich gehe davon aus, dass Sie dies aus irgendeinem Grund nicht können

Terence Honles
quelle
Ich glaube, ich habe Jimbobs Post nicht gesehen ... praktisch das Gleiche, ich rufe Einheimische / Globale nur nicht mehr als einmal an
Terence Honles
Ich denke nicht, dass es effizienter wäre, Globals mehr als einmal anzurufen.
Dr. Jimbob
ZB wenn Sie Elemente tun = local (); id (local ()) == id (items) Sie würden Gleichheit erhalten. Oder wenn du Elemente gemacht hast = local (); b = 3; items ['b'] findet die neue Variable b, da das lokale Diktat nicht in Elemente kopiert wurde (was langsamer wäre). Wenn Sie items = local (). Copy () ausgeführt haben, liegt möglicherweise ein geringfügiger Unterschied vor. Andererseits ist der Kopierschritt wahrscheinlich langsamer als der Zugriff auf die geringe Anzahl von Elementen aus dem Diktat der Einheimischen.
Dr. Jimbob
-1

Versuchen:

to_dict = lambda **k: k
apple = 1
banana = 'f'
carrot = 3
to_dict(apple=apple, banana=banana, carrot=carrot)
#{'apple': 1, 'banana': 'f', 'carrot': 3}
Prv
quelle
1
Wie unterscheidet es sich von einfach zu tun dict(apple=apple, banana=banana, carrot=carrot)?
Basit Ali
-1

Nicht die eleganteste Lösung und funktioniert nur in 90% der Fälle:

def vardict(*args):
    ns = inspect.stack()[1][0].f_locals
    retval = {}
    for a in args:
        found = False
        for k, v in ns.items():
            if a is v:
                retval[k] = v
                if found:
                    raise ValueError("Value found in more than one local variable: " + str(a))
                found = True
        if found:
            continue
        if 'self' in ns:
            for k, v in ns['self'].__dict__.items():
                if a is v:
                    retval[k] = v
                    if found:
                        raise ValueError("Value found in more than one instance attribute: " + str(a))
                    found = True
        if found:
            continue
        for k, v in globals().items():
            if a is v:
                retval[k] = v
                if found:
                    raise ValueError("Value found in more than one global variable: " + str(a))
                found = True
        assert found, "Couldn't find one of the parameters."
    return retval

Sie werden auf Probleme stoßen, wenn Sie dieselbe Referenz in mehreren Variablen speichern, aber auch, wenn mehrere Variablen dieselbe kleine int speichern, da diese interniert werden.

Aleksandr Dubinsky
quelle
-2

warum machst du nicht das Gegenteil:

fruitdict = { 
      'apple':1,
      'banana':'f',
      'carrot':3,
}

locals().update(fruitdict)

Update:

Verwenden Sie nicht den obigen Code. Überprüfen Sie den Kommentar.

Übrigens, warum du die Vars, die du bekommen willst, nicht markierst, weiß ich vielleicht nicht so:

# All the vars that i want to get are followed by _fruit
apple_fruit = 1
carrot_fruit = 'f'

for var in locals():
    if var.endswith('fruit'):
       you_dict.update({var:locals()[var])
Mouad
quelle
4
So zu aktualisieren locals()ist wirklich böse.
Greg Hewgill
Wie ein Freund von mir sagt: "Dark Voodoo"
Caleb Hattingh
stimme zu, aber mein Verständnis seiner Frage ist, dass er nur Variablen erhalten möchte, die Obst und Hülsenfrüchte sind ; Das ist im Grunde unmöglich, es sei denn, er könnte seinem Programm beibringen, zwischen Obst und Hülsenfrüchten und anderen Dingen zu unterscheiden , oder vielleicht kompliziere ich die Sache, vielleicht will er nur "Karotten, Bananen, Apfel" -Vars :)
Mouad
3
Das Aktualisieren von local () ist verboten docs.python.org/library/functions.html#locals
John La Rooy
-4
a = "something"
randround = {}
randround['A'] = "%s" % a

Hat funktioniert.

user1734291
quelle
1
Es sollte sein {'a' : 'something'}und Sie bekommen {'A' : 'something'}... Sie sind schwer, den Schlüssel zu codierenA
DarkCygnus