Verkettung von Variablen

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
der kleine Fritz
User
Beiträge: 25
Registriert: Montag 18. Dezember 2023, 11:33

Hallo,
ich hab folgendes Problem:
Ich möchte mehrere Variablen als Ergebnisausgabe miteinander verketten. In meinem Code gibt es jedoch die Möglichkeit das eine oder mehrere der Variablen je nach Eingabe leer bzw nicht existent sind. Sobald jedoch eine Variable fehlt, meckert Python das ein Wert fehlt.
Die Verkettung haben ich ganz banal mit "+" aber auch micht "join" und "(f"{x},{y},...") versucht aber ohne Erfolg.
Wie könnte ich das Problem lösen?
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

Poste ein möglichst konkretes Beispiel, das Dein Problem zeigt. Was genau meckert Python?
Denn leere Werte filtern stellt ja keine so große Hürde da:

Code: Alles auswählen

result = ",".join(value for value in values if values)
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

"leer" und "nicht existent sind in dem Fall ein ziemlicher Unterschied.

Wenn die Variablen ggf. leer sind kann man das z.B. so machen:

Code: Alles auswählen

>>> a = 'Hallo'
>>> b = ''
>>> c = 'Welt'
>>> collected_vars = [a, b, c]
>>> ' '.join([var for var in collected_vars if var])
'Hallo Welt'
>>> b = 'gute'
>>> collected_vars = [a, b, c]
>>> ' '.join([var for var in collected_vars if var])
'Hallo gute Welt'
>>>
Wenn eine Variable nicht existent ist wird es aufwendiger, weil man mit Fehlerbehandlungen hantieren muss.

Das eine Variable leer _oder_ nicht existent ist, ist... ungewöhnlich. Warum ist die Variable ggf. nicht existent statt leer bzw. mit `None` belegt?

Gruß, noisefloor
der kleine Fritz
User
Beiträge: 25
Registriert: Montag 18. Dezember 2023, 11:33

Python schimpft:
UnboundLocalError: cannot access local variable 'ausgabe_M' where it is not associated with a value

Aber ich versuche mal deinen Tipp aus! Danke!
der kleine Fritz
User
Beiträge: 25
Registriert: Montag 18. Dezember 2023, 11:33

@noisefloor
es geht tatsächlich um "nicht existen"!
Genaugenommen schreibe ich aus Spaß und Hobby an einem Code, der z.B. Dezimalzahlen in Römische Zahlen umwandelt und da kann es je nachdem sein das "M" oder "D" usw. nicht vorkommt. Ich möchte sozusagen die Dezimalzahl der Größe nach zerlegen (von hoch nach niedrig) und in eine Römische Zahl umwandeln.
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

dann wäre es IMHO zumindest bei den römischen Zahl, am einfachsten, wenn du alle Zeichen mit `None` vorbelegst und im Code dann nach Notwendigkeit bzw.Zahl überschreibst. Dann funktioniert auch das von Sirius3 und mir gezeigt vorgehen mit der List Comprehension.

Für konkretere oder ggf. besser Tipps müsstest du mal deinen relevanten Code zeigen.

Gruß, noisefloor
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@der kleine Fritz: nicht existente Variablen sind immer ein Programmierfehler, Du muß dafür sogen, dass alle Variablen immer existieren, eventuell mit dem Wert None oder "".
Dass der Fall überhaupt auftritt, deutet darauf hin, dass Du die einzelnen Werte explizit ausprogrammiert hast, was man normalerweise versucht zu vermeiden, weil es meist besser ist, mit passenden Datenstrukturen zu arbeiten:

Code: Alles auswählen

ROMAN_NUMERALS = [
    ("M", 1000),
    ("CM", 900),
    ("D", 500),
    ("CD", 400),
    ("C", 100),
    ("XC", 90),
    ("L", 50),
    ("XL", 40),
    ("X", 10),
    ("IX", 9),
    ("V", 5),
    ("IV", 4),
    ("I", 1),
]
der kleine Fritz
User
Beiträge: 25
Registriert: Montag 18. Dezember 2023, 11:33

okay, das sind doch gute Hinweise die ich mal versuche umzusetzten.
@Sirius3: es stimmt ich habe tatsächlich die einzelnen Werte ausprogrammiert, da ich noch Python-Anfänger bin.
Danke für eure Antworten!

Und hier der Code bis jetzt:

Code: Alles auswählen

def Umrechner_römische_Zahlen (eingangswert):
    #Prüfung und Berechnung ob Eingabewert über 1000 und somit wieviel M 
    if eingangswert >= 1000:
        M = eingangswert // 1000
        restM = eingangswert - M*1000
        ausgabe_M = M*("M")
          
    #Prüfung und Berechnung ob Eingabewert über 500 aber kleiner 1000 für D
    if eingangswert >= 500 and eingangswert < 1000 or restM >= 500:
        D = eingangswert or restM // 500
        restD = eingangswert or restM - 500
        ausgabe_D = ("D") 
    
    ergebnis = (f"{ausgabe_M}{ausgabe_D}")
    
    return ergebnis
    

eingangswert = int(input("Gib eine Zahl an die als römische Zahl umgerechnet werden soll: "))
Umrechner_römische_Zahlen (eingangswert)
ergebnis = Umrechner_römische_Zahlen (eingangswert)
print (ergebnis)
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Unabhaengig von Fragen des Stils ist das ja schon deshalb falsch, weil du nur *einmal* abfragst, ob eine Zahl groesser als der aktuelle Schwellwert ist. Das ist natuerlich Quatsch, zB das Jahr 2000+ braucht ja nunmal zweimal M. Und das wird noch offensichtlicher bei kleineren Werten. Darum muessen das mindestens mal while-Schleifen werden.
der kleine Fritz
User
Beiträge: 25
Registriert: Montag 18. Dezember 2023, 11:33

__deets__ hat geschrieben: Freitag 5. Januar 2024, 11:47 Unabhaengig von Fragen des Stils ist das ja schon deshalb falsch, weil du nur *einmal* abfragst, ob eine Zahl groesser als der aktuelle Schwellwert ist. Das ist natuerlich Quatsch, zB das Jahr 2000+ braucht ja nunmal zweimal M. Und das wird noch offensichtlicher bei kleineren Werten. Darum muessen das mindestens mal while-Schleifen werden.
also mehrere 1000 (M) werden in dem code schon berücksichtigt. Aber das mit der Einbindung einer While-Schleife macht natürlich auch sinn.
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@der kleine Fritz: bei dir fehlt einfach nur ein else-Block mit `ausgabe_M = ""`, dann sind immer alle Variablen definiert.

Funktionsnamen werden wie Variablennamen komplett klein geschrieben.
Du hast immer Klammern um Deine Strings? Die sollten weg.
Bei der if-Abfrage zu 500 hast Du dann Glück, weil Python nicht den gesamten Ausdruck auswertet und schon mit eingangswert < 1000 zufrieden ist, und restM gar nicht mehr abfragt, im Falle, dass es nicht definiert ist.
Bei `D = eingangswert or restM // 500` bist Du dann sehr am raten und hoffst, dass Deine umgangssprachliche Formulierung vom Computer richtig interpretiert wird (PS: tut sie nicht)
Wenn man das alles etwas aufräumt, kommt man ungefähr hier raus:

Code: Alles auswählen

def umrechner_römische_zahlen(eingangswert):
    if eingangswert >= 1000:
        anzahl = eingangswert // 1000
        rest = eingangswert - anzahl * 1000
        ausgabe_M = anzahl * "M"
    else:
        rest = eingangswert
        ausgabe_M = ""
          
    if rest >= 500:
        rest -= 500
        ausgabe_D = "D" 
    else:
        ausgabe_D = ""
    
    return f"{ausgabe_M}{ausgabe_D}"
Eine Variante mit oben bereits genannter Datenstruktur:

Code: Alles auswählen

ROMAN_NUMERALS = [
    ("M", 1000),
    ("CM", 900),
    ("D", 500),
    ("CD", 400),
    ("C", 100),
    ("XC", 90),
    ("L", 50),
    ("XL", 40),
    ("X", 10),
    ("IX", 9),
    ("V", 5),
    ("IV", 4),
    ("I", 1),
]

def convert_to_roman(number):
    result = []
    for text, value in ROMAN_NUMERALS:
        while number >= value:
            result.append(text)
            number -= value
    return ''.join(result)

def convert_from_roman(romannumber):
    result = 0
    for text, value in ROMAN_NUMERALS:
        while romannumber.startswith(text):
            romannumber = romannumber[len(text):]
            result += value
    if romannumber:
        raise ValueError(romannumber)
    return result
der kleine Fritz
User
Beiträge: 25
Registriert: Montag 18. Dezember 2023, 11:33

@sirius3: Danke ich werde es mit der Variante versuche ohne mir deinen Code anzuschauen. Wenn ich nicht weiter weiß, werde ich aber mal reinschielen. :-)
Antworten