Keys aus nested Dictionary in globale Attruibute umwandeln

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
test.py
User
Beiträge: 9
Registriert: Montag 23. September 2019, 11:04

Hi,

ich möchte erreichen, mehrere alternative Einstellungspresets zu definieren und ein bestimmtes Preset mittels Zuweisung zu selektieren. Im restlichen Programm soll dann mit generischen Bezeichnern gearbeitet werden können, die je nach ausgewählter Einstellung verschiedene Werte annehmen.
Einfaches Beispiel:

Code: Alles auswählen

LAYOUT_BORING = {
	"TEXTBOX_PREFIX": "# ",
	"TEXTBOX_HEADING": "# " + "=" * 80,
	"TEXTBOX_INDENT": "    "
	}
LAYOUT_FANCY = {
	"TEXTBOX_PREFIX": "| ",
	"TEXTBOX_HEADING": "| " + "=" * 80,
	"TEXTBOX_INDENT": "    "
	}
LAYOUT = LAYOUT_FANCY

print(LAYOUT["TEXTBOX_HEADING"])
print(LAYOUT["TEXTBOX_PREFIX"] + "Items:")
print(LAYOUT["TEXTBOX_PREFIX"] + LAYOUT["TEXTBOX_INDENT"] + "Item 1")
So weit, so gut. Nun würde ich gerne auch bereits hingeschriebene Einträge in einem Dictionary in diesem auch gleich verwenden können. Dazu habe ich im Netz diese Variante gefunden:

Code: Alles auswählen

class NestedDict(dict):
	def __getitem__(self, item):
		return dict.__getitem__(self, item) % self

LAYOUT_BORING = NestedDict({
	"TEXTBOX_PREFIX" : "# ",
	"TEXTBOX_HEADING" : "%(TEXTBOX_PREFIX)s" + "=" * 80,
	"TEXTBOX_INDENT" : "    "
})
LAYOUT_FANCY = NestedDict({
	"TEXTBOX_PREFIX": "| ",
	"TEXTBOX_HEADING": "%(TEXTBOX_PREFIX)s" + "=" * 80,
	"TEXTBOX_INDENT": "    "
})
LAYOUT = LAYOUT_FANCY

print(...)
Jetzt will ich aber meinen eigentlichen Code, der folgt, auch nicht so aufgebläht und unleserlich haben. Schöner wäre es, globale Attribute nutzen zu können. Das könnte ich folgendermaßen erreichen:

Code: Alles auswählen

globals().update(LAYOUT)

print(TEXTBOX_HEADING)
print(TEXTBOX_PREFIX + "Items:")
print(TEXTBOX_PREFIX + TEXTBOX_INDENT + "Item 1")
Das wäre schön, funktioniert aber nicht, weil das Nesting hierdurch kaputtgeht. Wie könnte ich das fixen? Ich finde zu diesem Problem leider nichts wirklich ...

(und falls jemand von euch eine Idee hat, wie ich mein ursprüngliches Problem mit den Presets schöner und eleganter lösen kann, bin ich auch für Vorschläge offen.)
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

Solche `globals`-Spielereien machen den Code nicht übersichtlicher, sondern undurchsichtiger. Die Zugriffe auf `LAYOUT` finden ja auch nicht überall statt, sondern nur in sehr wenigen Funktionen, mit denen Du dann komplexere Textboxen generieren kannst.
test.py
User
Beiträge: 9
Registriert: Montag 23. September 2019, 11:04

Hi,

ob das den Code übersichtlicher macht, war zum einen ja gar nicht die Frage, zum anderen geht es im realen Anwendungsfall nicht nur um Textboxen, sondern um allerlei Dinge, um Text formatiert auszugeben. Die Textbox sollte nur als einfach verständliches Beispiel dienen. :)
In meinem Fall werden diese Dinge auch ständig verwendet, um Strings die gewünschte Farbe, den gewünschten Abstand, den gewünschten Separator etc. zu geben. Die Variante mit LAYOUT["KEY"] ist da doch sehr sperrig, wenn es zigmal in einer Zeile benutzt werden soll ... gäbe es kein "Problem" damit, hätte ich schließlich nicht in einem Forum gepostet.

LG
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Mit globals geht es halt nicht, das ist nunmal ein eingebautes dict, und nicht deine eigene Unterklasse. Und das wird sich jenseits von selbst-komplieren des Interpreters auch nicht aendern lassen. Und was nun so ein Problem an einem immer genutzen Praefix wie zB L ist - 🤷‍♂️

Code: Alles auswählen

from my_layout_definitions import L

def tralala():
     print(L.TEXBOX.PREFIX)
Benutzeravatar
__blackjack__
User
Beiträge: 14047
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@test.py: Ob es den Code übersichtlicher macht ist immer Teil der Frage.

Wenn Du nicht ``LAYOUT["TEXTBOX_HEADING"]`` schreiben willst, dann nenn das Wörterbuch halt nicht `LAYOUT` sondern `TEXTBOX` und lass bei den Schlüsseln den "TEXTBOX"-Präfix weg: TEXTBOX["HEADING" ]``. Und man könnte auch Klassen statt Wörterbüchern verwenden: ``TEXTBOX.HEADING`` und wäre bei der gleichen Anzahl von Zeichen wie bei ``TEXTBOX_HEADING``.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
test.py
User
Beiträge: 9
Registriert: Montag 23. September 2019, 11:04

__deets__ hat geschrieben: Mittwoch 25. September 2019, 15:27 Mit globals geht es halt nicht, das ist nunmal ein eingebautes dict, und nicht deine eigene Unterklasse. Und das wird sich jenseits von selbst-komplieren des Interpreters auch nicht aendern lassen.
Also ohne das Nesting geht es ja, ich hätte es nur eben gerne mit Nesting gehabt. Ich dachte, das wird schon iwie gehen ...
__deets__ hat geschrieben: Mittwoch 25. September 2019, 15:27 Und was nun so ein Problem an einem immer genutzen Praefix wie zB L ist - 🤷‍♂️

Code: Alles auswählen

from my_layout_definitions import L

def tralala():
     print(L.TEXBOX.PREFIX)
Was muss ich denn tun, um auf diese Weise auf das Dictionary zuzugreifen? Kriege das so nicht reproduziert.
Und einen derart kurzen Bezeichner kann ich nicht nehmen, es muss für andere Leute im Team schon noch sprechend genug sein.
__blackjack__ hat geschrieben: Mittwoch 25. September 2019, 15:29 @test.py: Ob es den Code übersichtlicher macht ist immer Teil der Frage.
Wie meinst du das? Also den mir vorliegenden Code würde es definitiv lesbarer machen. Das muss ich am Ende ja selbst entscheiden, ob ich das wünsche oder nicht, und ich wünsche es. :)
Wäre halt schön, wenn es da eine elegante Möglichkeit gäbe.
__blackjack__ hat geschrieben: Mittwoch 25. September 2019, 15:29 Wenn Du nicht ``LAYOUT["TEXTBOX_HEADING"]`` schreiben willst, dann nenn das Wörterbuch halt nicht `LAYOUT` sondern `TEXTBOX` und lass bei den Schlüsseln den "TEXTBOX"-Präfix weg: TEXTBOX["HEADING" ]``. Und man könnte auch Klassen statt Wörterbüchern verwenden: ``TEXTBOX.HEADING`` und wäre bei der gleichen Anzahl von Zeichen wie bei ``TEXTBOX_HEADING``.
Eine Config-Klasse wäre evtl. eine Option. Am Ende würde ich die Konfiguration aber gerne aus einer JSON-Datei einlesen, darum blieb ich bisher beim Dictionary, weil es da bereits passende Funktionen gibt. Also bevorzugt wäre ein Dictionary, aber ich überleg mal, ob ich das auch mit Klasse hinkriege. :)
Benutzeravatar
sparrow
User
Beiträge: 4538
Registriert: Freitag 17. April 2009, 10:28

Dein Beitrag ist leicht schizophren. Auf der einen Seite willst du keine kurzen Bezeichner, weil andere im "Team" das auch verstehen müssen, gleichzeitig willst du aber krude Dinge tun, die niemand in Python so machen würde.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wenn die Leute lernen, dass magisch Konstanten entstehen, lernen die auch einen Präfix zu benutzen. Und es geht halt auch nicht anders. Wünsche hin oder her.

Den Zugriff ohne [""] erreichst du mit __getitem__. Aufpassen musst du natürlich das die genestelten Dicts wieder von deiner Klasse sind. Das gilt aber ja schon jetzt.
Benutzeravatar
__blackjack__
User
Beiträge: 14047
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Für Attributzugriff auf (verschachtelte) Wörterbücher verwende ich in der Regel `addict.Dict`.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

Und das ganze mit einer JSON-Konfigurationsdatei:

Code: Alles auswählen

with open('layout.json', encoding="utf8") as data:
    layout = json.load(data, object_hook=addict.Dict)
textbox = layout.textbox
Antworten