locals() verstehen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
RedSharky
User
Beiträge: 99
Registriert: Donnerstag 13. April 2006, 15:38

Hallo,

bitte: Was unterscheidet in meinem Beispiel a von b? Warum sind nicht beide local(), oder doch? Warum kann ich auf b nicht zugreifen wie auf a???

Kann mir das einer erklären? Danke!

Code: Alles auswählen

#!/usr/bin/python

def main():
    print "locals:"; print locals(); print
    
    a = "b"
    vars()[a] = 100
    
    print "locals:"; print locals(); print
    
    print a
    print b

if __name__ == "__main__":
    main()
Die Ausgabe:

Code: Alles auswählen

locals:
{}

locals:
{'a': 'b', 'b': 100}

b
Traceback (most recent call last):
  File "understanding_locals.py", line 16, in <module>
    main()
  File "understanding_locals.py", line 13, in main
    print b
NameError: global name 'b' is not defined
lunar

RTFM:
Return the __dict__ attribute for a module, class, instance, or any other object with a __dict__ attribute.

Objects such as modules and instances have an updateable __dict__ attribute; however, other objects may have write restrictions on their __dict__ attributes (for example, new-style classes use a dictproxy to prevent direct dictionary updates).

Without an argument, vars() acts like locals(). Note, the locals dictionary is only useful for reads since updates to the locals dictionary are ignored.
.
Die selbe Warnung steht ziemlich groß und eigentlich unübersehbar auch nochmal in der Dokumentation zu "locals()".
RedSharky
User
Beiträge: 99
Registriert: Donnerstag 13. April 2006, 15:38

Es geht also warum auch immer nicht. Wie könnte ich denn dann zum gewünschten Ergebnis kommen? Wenn es irgendwie besser geht, bin ich für jeden Vorschlag dankbar.
deets

Was ist denn das eigentliche Problem, das du loesen willst? Ich hatte noch nie das Beduerfnis, lokale Variablen anzulegen - schliesslich braucht es dann auch code, der auf die Zugreift. Willst du den auch generieren?

Stattdessen nimmt man halt einfach direkt ein Dictionary, und speichert darin seine Daten.
RedSharky
User
Beiträge: 99
Registriert: Donnerstag 13. April 2006, 15:38

Es geht darum aus Strings Variablennamen zu machen und umgekehrt - und ohne an den globals() herumzuspielen.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

RedSharky hat geschrieben:Es geht darum aus Strings Variablennamen zu machen und umgekehrt - und ohne an den globals() herumzuspielen.
Wozu sollte das gut sein? Oder meinst Du getattr?
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
deets

RedSharky hat geschrieben:Es geht darum aus Strings Variablennamen zu machen und umgekehrt - und ohne an den globals() herumzuspielen.
Das ist schon klar, dass du das versuchst. *WARUM* ist aber noch nicht klar. Wer greift denn dann auf deine schoenen neuen Variablen zu?
RedSharky
User
Beiträge: 99
Registriert: Donnerstag 13. April 2006, 15:38

Ok, ich versuche mit dem ConfigParser viele Variablen in eine Konfigurationsdatei zu speichern. Dazu möchte ich den Variablennamen automatisch zum Option-Namen machen. Das müsste man sonst per Hand für jede Variable machen. Natürlich soll das ganze bei Auslesen wieder automatisch passieren.

Python (Variablenname = Wert):
myarbtrvar = 100

zu:

Config-Inhalt (Option = Value):
myarbtrvar = 100

Wenn das mit getattr geht, dann freue ich mich über ein Beispiel, denn ich kann so nicht sehen, wie das funktionieren soll...
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

lunar hat geschrieben:
Note, the locals dictionary is only useful for reads since updates to the locals dictionary are ignored.
Du kannst also über „locals“ darauf zugreifen, aber damit keine Variablen verändern!
RedSharky
User
Beiträge: 99
Registriert: Donnerstag 13. April 2006, 15:38

Ist klar, nur wie macht man es sonst? Aus einem String soll ein Variablenname gemacht werden bzw. eine neue Variable angelegt werden.
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

RedSharky hat geschrieben:Ist klar, nur wie macht man es sonst? Aus einem String soll ein Variablenname gemacht werden bzw. eine neue Variable angelegt werden.
Wozu soll daraus ein Variablenname gemacht werden? Hilft dir das?

Code: Alles auswählen

In [3]: a = 'foo'

In [4]: locals()['a']
Out[4]: 'foo'
Edit: „Natürlich soll das ganze bei Auslesen wieder automatisch passieren.“ — hab ich natürlich übersehen.
Zuletzt geändert von nomnom am Freitag 2. März 2012, 18:47, insgesamt 1-mal geändert.
deets

RedSharky hat geschrieben:Ok, ich versuche mit dem ConfigParser viele Variablen in eine Konfigurationsdatei zu speichern. Dazu möchte ich den Variablennamen automatisch zum Option-Namen machen. Das müsste man sonst per Hand für jede Variable machen. Natürlich soll das ganze bei Auslesen wieder automatisch passieren.

Python (Variablenname = Wert):
myarbtrvar = 100

zu:

Config-Inhalt (Option = Value):
myarbtrvar = 100

Wenn das mit getattr geht, dann freue ich mich über ein Beispiel, denn ich kann so nicht sehen, wie das funktionieren soll...
Das ist der falsch Ansatz. Du willst nicht wirklich deinen Variablen-Raum automatisch mit Konfigurations-Variablen zumuellen.

Stattdessen solltest du zB ein Bunch-Rezept benutzen, um ein Dictionary (nichts anderes sind die Config-Objekte ja am Ende) zu einem Objekt zu machen, auf dessen Attribute du dann simpel zugreifen kannst:

Code: Alles auswählen


class Bunch(object):

   def __init__(self, **kwargs):
         self.__dict__.update(kwargs)


config_dict = dict(foo="bar")

config = Bunch(**config_dict)

... # im code spaeter dann:

if config.foo == 'bar':
    ...

mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@deets:
Und welchen Vorteil hat Deine Bunch-Klasse gegenüber einem simplen dictionary?

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
deets

Die kompaktere Schreibweise. Es fehlen halt ein paar Anfuehrungszeichen und Klammern. Dadurch sieht der Code durchaus etwas aufgeraeumter aus.
RedSharky
User
Beiträge: 99
Registriert: Donnerstag 13. April 2006, 15:38

Danke für die guten Ideen. Ich werd das jetzt so wie von deets vorgeschlagen machen:

Code: Alles auswählen

class Bunch:
    pass

cfg = Bunch()

cfg.a = 1
cfg.b = 2
print cfg.__dict__
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

@RedSharky: Schau dir nochmal deets' Bunch-Klasse an. Die funktioniert anders, als deine.
In specifications, Murphy's Law supersedes Ohm's.
Antworten