Hallo,
ich habe verschiedene Variablen gesetzt. In Wirklichkeit sind es wesentlich mehr Variablen, ich habe den Code hier nur zur Demonstration reduziert.
Ich möchte jeweils den MAX-Value dieser Variablen erhalten, wobei die Variablennamen "variabel" sind (so wie ich es bis jetzt gemacht habe).
Beim "print" bekomme ich allerdings nicht den erwarteten Wert (3 bzw. 3.3), sondern "a_1_03" bzw. "b_1_03".
Was habe ich falsch gemacht bzw. kann man das anders lösen?
LG,
bernie70
[code]
a_1_01 = 1
a_1_02 = 2
a_1_03 = 3
b_1_01 = 1.1
b_1_02 = 2.2
b_1_03 = 3.3
for param in ['a', 'b']:
globals()[f'{param}_1_0103'] = max(param + "_1_01", param + "_1_02", param + "_1_03")
print(a_1_0103)
print(b_1_0103)
[/code]
MAX-Value aus "variablen" Variablen
Das sieht schwer danach aus, dass was du eigentlich brauchst, die richtigen Datenstrukturen sind. Man baut keine solchen durchnummerierten Konglomerate von Variablennamen. Und vor allem legt man nicht auch noch selbst globale Variablen an!
Richtig saehe das zb so aus:
Niemals in meinen >20 Jahren Python habe ich das globals()-Woerterbuch in so einer Art gebraucht. Das ist kein sinnvolles vorgehen.
Richtig saehe das zb so aus:
Code: Alles auswählen
the_as = {
1: 1,
2: 2,
3: 3,
}
the_bees = {
1: 1.1,
...
}
parameters = {}
for name, things in [("a", the_as), ("b", the_bees)]:
parameters[name] = max(things.values()
Das ist sehr fragil und fehlerträchtig, was du da machst und ein Beispiel, wie man in Python nicht vorgehen sollte. Besser ist es die Werte für a und b, denn die scheinen gruppiert zusammenzugehören, z.B. in Listen zu speichern. Dann reicht ein einfacher Aufruf von max():
Code: Alles auswählen
a = [1, 2, 3]
max(a)
- __blackjack__
- User
- Beiträge: 13931
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
Wobei das die im Grunde die gleiche Antwort ist, die bernie70 for 13 Jahren schon mal gegeben wurde: Variable aus Variable erstellen. Aber ich vermute, dem Inhalt des letzten Beitrags nach, dass damals schon die ”Lösung” mit `globals()` gefunden wurde. 
“Java is a DSL to transform big Xml documents into long exception stack traces.”
— Scott Bellware
— Scott Bellware
Du nimmst nur das "Maximum" von Strings. Also dann in deinem (lokalen) Konstrukt..
Code: Alles auswählen
a_1_01 = 1
a_1_02 = 2
a_1_03 = 3
b_1_01 = 1.1
b_1_02 = 2.2
b_1_03 = 3.3
for param in ['a', 'b']:
locals()[f'{param}_1_0103'] = max(locals()[param + "_1_01"], locals()[param + "_1_02"], locals()[param + "_1_03"])
print(a_1_0103)
print(b_1_0103)
3
3.3
- __blackjack__
- User
- Beiträge: 13931
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
Wobei `locals()` hier objektiv falsch ist, weil das nur funktioniert sofern `locals()` das *selbe* Ergebnis wie `globals()` liefert, denn tatsächlich lokale Namensräume kann man mindestens mal in CPython nicht um neue Namen erweitern. Das ist auch explizit dokumentiert.
Mein Beitrag zum Horrorkabinett wäre:
Mein Beitrag zum Horrorkabinett wäre:
Code: Alles auswählen
global_variables = globals()
global_variables.update(
(
f"{param}_1_0103",
max(global_variables[f"{param}_1_0{i}"] for i in range(1, 4)),
)
for param in ["a", "b"]
)
“Java is a DSL to transform big Xml documents into long exception stack traces.”
— Scott Bellware
— Scott Bellware
@__blackjack__: das macht es aber sehr schwierig, das Programm anzupassen, wenn man mal von mehr als drei Variablen das Maximum ermitteln möchte:
Code: Alles auswählen
MIN_VARIABLE_INDEX = 1
MAX_VARIABLE_INDEX = 3
global_variables = globals()
global_variables.update(
(
f"{param}_1_0{MIN_VARIABLE_INDEX}0{MAX_VARIABLE_INDEX}",
max(global_variables[f"{param}_1_0{i}"] for i in range(MIN_VARIABLE_INDEX, MAX_VARIABLE_INDEX + 1)),
)
for param in ["a", "b"]
)
Ganz so kann man das wohl nicht sagen:__blackjack__ hat geschrieben: ↑Donnerstag 8. Juni 2023, 07:52 Wobei `locals()` hier objektiv falsch ist, weil das nur funktioniert sofern `locals()` das *selbe* Ergebnis wie `globals()` liefert, denn tatsächlich lokale Namensräume kann man mindestens mal in CPython nicht um neue Namen erweitern. Das ist auch explizit dokumentiert.
Locals und Globals sind identisch auf Modulebene, ansonsten bekommt jeder Kontext eine eigene (leere) Locals aber mit Scope auf Globals.
Änderungen in Locals sind dann eben auch nur im jeweiligen (lokalen) Kontext sichtbar.
Allerdings hast du Recht damit, dass man mit expliziten Änderungen von Locals i.a. vorsichtig sein sollte..
Note The contents of this dictionary should not be modified; changes may not affect the values of local and free variables used by the interpreter.
Code: Alles auswählen
def test_locals():
a_1_01 = 1
a_1_02 = 2
a_1_03 = 3
b_1_01 = 1.1
b_1_02 = 2.2
b_1_03 = 3.3
for param in ['a', 'b']:
locals()[f'{param}_1_0103'] = max(locals()[param + "_1_01"], locals()[param + "_1_02"], locals()[param + "_1_03"])
print(locals()['a_1_0103'])
print(locals()['b_1_0103'])
print(a_1_0103) # NameError
test_locals()
Natürlich ist das aber alles Gefrickel und sollte vermieden werden. Es gibt m.E. auch keinen wirklichen Grund für "Variablenstrings".3
3.3
Traceback (most recent call last):
..
print(a_1_0103) # NameError
^^^^^^^^
NameError: name 'a_1_0103' is not defined. Did you mean: 'a_1_01'?
Zuletzt geändert von Qubit am Donnerstag 8. Juni 2023, 12:43, insgesamt 1-mal geändert.
@Qubit: wie soll man denn sonst dazu sagen, wenn ein Code der `locals` benutzt, nicht funktioniert?
Und "sollte nicht verändert werden" ist auch etwas anderes als "vorsichtig sein".
Führt man Deinen Code in einer Funktion aus, bekommt man den Fehler:
Und "sollte nicht verändert werden" ist auch etwas anderes als "vorsichtig sein".
Führt man Deinen Code in einer Funktion aus, bekommt man den Fehler:
Code: Alles auswählen
NameError: name 'a_1_0103' is not defined
Ich habe mal meinen letzten Beitrag um das Beispiel erweitert, wie es mit "Vorsicht" bei Locals funktioniert..Sirius3 hat geschrieben: ↑Donnerstag 8. Juni 2023, 12:42 @Qubit: wie soll man denn sonst dazu sagen, wenn ein Code der `locals` benutzt, nicht funktioniert?
Und "sollte nicht verändert werden" ist auch etwas anderes als "vorsichtig sein".
Führt man Deinen Code in einer Funktion aus, bekommt man den Fehler:Code: Alles auswählen
NameError: name 'a_1_0103' is not defined
- __blackjack__
- User
- Beiträge: 13931
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@Qubit: Mit ”funktioniert” meinte ich, dass das wirklich generell funktioniert, und nicht nur zufällig. Denn es mag ja so sein das `locals()` auf Modulebene das gleiche wie `globals()` liefert, aber das muss es nicht. Die Anmerkung in der Dokumentation ist da deutlich. In anderen Implementierungen als CPython kann das anders aussehen und auch in CPython können die Entwickler sich entscheiden bei `locals()` auf Moduleben etwas anderes zurück zu geben. Auf der anderen Seite könnte das ändern auch in Funktionen ”funktionieren”. Sind halt Implementierungsdetails.
“Java is a DSL to transform big Xml documents into long exception stack traces.”
— Scott Bellware
— Scott Bellware
Ja, da hast du völlig Recht!__blackjack__ hat geschrieben: ↑Donnerstag 8. Juni 2023, 12:55 @Qubit: Mit ”funktioniert” meinte ich, dass das wirklich generell funktioniert, und nicht nur zufällig. Denn es mag ja so sein das `locals()` auf Modulebene das gleiche wie `globals()` liefert, aber das muss es nicht. Die Anmerkung in der Dokumentation ist da deutlich. In anderen Implementierungen als CPython kann das anders aussehen und auch in CPython können die Entwickler sich entscheiden bei `locals()` auf Moduleben etwas anderes zurück zu geben. Auf der anderen Seite könnte das ändern auch in Funktionen ”funktionieren”. Sind halt Implementierungsdetails.
Letzte Bemerkung von mir dazu..
wenn man tatsächlich solche "Stringvariablen" benutzen und davon welche im weiteren Kontext verwenden will (wie diese Max-Variablen), dann würde ich im jeweiligen Kontext ein Dict definieren (ggfs. auf Modulebene so ein "string_vars" definieren)..
Code: Alles auswählen
string_vars = {}
def test_locals():
a_1_01 = 1
a_1_02 = 2
a_1_03 = 3
b_1_01 = 1.1
b_1_02 = 2.2
b_1_03 = 3.3
for param in ['a', 'b']:
string_vars[f'{param}_1_0103'] = max(vars()[param + '_1_01'], vars()[param + '_1_02'], vars()[param + '_1_03'])
test_locals()
print(string_vars)
#...string_vars
{'a_1_0103': 3, 'b_1_0103': 3.3}