Seite 1 von 1

MAX-Value aus "variablen" Variablen

Verfasst: Mittwoch 7. Juni 2023, 11:23
von bernie70
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]

Re: MAX-Value aus "variablen" Variablen

Verfasst: Mittwoch 7. Juni 2023, 11:30
von __deets__
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:

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()
Niemals in meinen >20 Jahren Python habe ich das globals()-Woerterbuch in so einer Art gebraucht. Das ist kein sinnvolles vorgehen.

Re: MAX-Value aus "variablen" Variablen

Verfasst: Mittwoch 7. Juni 2023, 11:34
von kbr
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)

Re: MAX-Value aus "variablen" Variablen

Verfasst: Mittwoch 7. Juni 2023, 11:38
von __blackjack__
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. ☹️

Re: MAX-Value aus "variablen" Variablen

Verfasst: Mittwoch 7. Juni 2023, 12:20
von bernie70
Vielen Dank für Eure Antworten.

Re: MAX-Value aus "variablen" Variablen

Verfasst: Mittwoch 7. Juni 2023, 22:59
von Qubit
bernie70 hat geschrieben: Mittwoch 7. Juni 2023, 11:23
Was habe ich falsch gemacht
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

Re: MAX-Value aus "variablen" Variablen

Verfasst: Mittwoch 7. Juni 2023, 23:04
von __deets__
Und immer gibts wen, der das Seil zum selber erhängen anreicht…

Re: MAX-Value aus "variablen" Variablen

Verfasst: Donnerstag 8. Juni 2023, 07:52
von __blackjack__
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:

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

Re: MAX-Value aus "variablen" Variablen

Verfasst: Donnerstag 8. Juni 2023, 08:55
von Sirius3
@__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"]
)

Re: MAX-Value aus "variablen" Variablen

Verfasst: Donnerstag 8. Juni 2023, 12:23
von Qubit
__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.
Ganz so kann man das wohl nicht sagen:
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()
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'?
Natürlich ist das aber alles Gefrickel und sollte vermieden werden. Es gibt m.E. auch keinen wirklichen Grund für "Variablenstrings".

Re: MAX-Value aus "variablen" Variablen

Verfasst: Donnerstag 8. Juni 2023, 12:42
von Sirius3
@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

Re: MAX-Value aus "variablen" Variablen

Verfasst: Donnerstag 8. Juni 2023, 12:45
von Qubit
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
Ich habe mal meinen letzten Beitrag um das Beispiel erweitert, wie es mit "Vorsicht" bei Locals funktioniert..

Re: MAX-Value aus "variablen" Variablen

Verfasst: Donnerstag 8. Juni 2023, 12:55
von __blackjack__
@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.

Re: MAX-Value aus "variablen" Variablen

Verfasst: Donnerstag 8. Juni 2023, 13:17
von Qubit
__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.
Ja, da hast du völlig Recht!

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}

Re: MAX-Value aus "variablen" Variablen

Verfasst: Donnerstag 8. Juni 2023, 13:30
von Sirius3
@Qubit: jetzt fängst Du auch noch an, mit globalen Variablen zu arbeiten!
Und warum jetzt vars() statt locals()? Macht es nicht besser.