Variable mit Funktion verändern

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
senseye
User
Beiträge: 15
Registriert: Sonntag 12. September 2021, 23:00

Hallo,

gibt es eine Möglichkeit eine Variable, die als Parameter an eine Funktion übergeben wird, innerhalb der Funktion zu verändern, ohne die Variable direkt anzusprechen, damit außerhalb der Funktion die Veränderung übernommen wird?

Beispiel:

Code: Alles auswählen

x = 10

def irgendwas(wert):
    wert = 15

irgendwas(x)
Ich möchte gern x auf diese Weise verändern, so das x nach dem Funktionsaufruf den Wert 15 besitzt.
Ist das möglich, ohne x in der Funktion direkt anzusprechen?
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Einfach den neuen Wert per return von der Funktion zurückgeben lassen. Den bindest du dann wieder an x.

Code: Alles auswählen

x = 10

def irgendwas(wert):
    wert = 15
    return wert

x = irgendwas(x)
senseye
User
Beiträge: 15
Registriert: Sonntag 12. September 2021, 23:00

Hallo,

danke für die schnelle Antwort, aber so meinte ich das nicht. War ein schlechtes Codebeispiel von mir, sorry.

Ich poste einfach mal den Code, um den es tatsächlich geht.
Das ist eine Aufgabe, bei der der Benutzer eingibt, wieviel Geld er zurückzahlen muss und das Programm ihm die Stückelung der Scheine und Münzen zurück gibt.

Code: Alles auswählen

betrag = float(input("Geldbetrag: "))
euro = int(betrag)
euro_s = int(betrag%5)
cent = int(round(betrag%1*100, 2))

euro_scheine = [500, 200, 100, 50, 20, 10, 5]
euro_stuecke = [2, 1]
cent_stuecke = [50, 20, 10, 5, 2, 1]

def abziehen(geld, werte, art, form):
    for wert in werte:
        anzahl = geld // wert
        geld %= wert
        print(f'{wert:3}-{art}-{form:<7}: {anzahl:2} - Bleiben {geld:3} {art}.')

print(f'Es müssen {euro} Euro und {cent} Cent zurückgegeben werden.')
abziehen(euro, euro_scheine, "Euro", "Scheine")
abziehen(euro_s, euro_stuecke, "Euro", "Stücke")
abziehen(cent, cent_stuecke, "Cent", "Stücke")

#-----------------------------------------------------------------------------------------------------------
print("\n", "-"*50, "\n")
#-----------------------------------------------------------------------------------------------------------

betrag = float(input("Geldbetrag: "))
euro = int(betrag)
euro_s = int(betrag%5)
cent = int(round(betrag%1*100, 2))

euro_scheine = [500, 200, 100, 50, 20, 10, 5]
euro_stuecke = [2, 1]
cent_stuecke = [50, 20, 10, 5, 2, 1]

print(f'Es müssen {euro} Euro und {cent} Cent zurückgegeben werden.')

for wert in euro_scheine:
    anzahl = euro // wert
    euro %= wert
    print(f'{wert:3}-Euro-Scheine: {anzahl:2} - Bleiben {euro:3} Euro und {cent:2} Cent.')
for wert in euro_stuecke:
    anzahl = euro_s // wert
    euro_s %= wert
    print(f'{wert:3}-Euro-Stücke : {anzahl:2} - Bleiben {euro_s:3} Euro und {cent:2} Cent.')
for wert in cent_stuecke:
    anzahl = cent // wert
    cent %= wert
    print(f'{wert:3}-Cent-Stücke : {anzahl:2} - Bleiben {euro:3} Euro und {cent:2} Cent.')
Die beiden Programme machen das Gleiche. Ich würde gerne die obere Version mit der Print-Ausgabe der unteren Version verwenden.

Mein Problem besteht darin, dass ich in der Funktion bei der print-Ausgabe nicht zwischen Euro und Cent unterscheiden kann, da ich ja bloß eine art an die Funktion übergebe.
Daher meine Frage, ob ich von innerhalb der Funktion irgendwie die Variablen (euro, euro_s, cent) mit verändern kann?
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@senseye: Die Antwort bleibt die gleiche. Man kann da nichts ausserhalb der Funktion ändern, was auch gut so ist, und man verwendet den Rückgabewert von Funktionen um Ergebnisse an den Aufrufer zu übermitteln. Und Variable(n) ”verändern” schreibt man dann üblichweise so, dass man die Werte übergibt, und die in der Funktion veränderten Werte zurück gibt, und wieder an die ursprünglichen Namen beim Aufrufer bindet. So wie snafu das mit dem `x` gezeigt hat.

Ich würde das Aufteilen des Betrags in drei Werte und die drei Listen auch so nicht machen. `euro_s` ist zudem kein guter Name, weil man dem Leser erklären muss, was das `_s` am Ende bedeuten soll. Statt der drei Listen würde ich eine verwenden wo neben dem Centbetrag jeweils die Einheit und Form gespeichert ist. Dann kann man das ganze mit *einem* Betrag, und *einer* Schleife über diese Liste lösen. Den die ``for``-Schleifen am Ende sehen ja nahezu identisch aus, weil da Daten als Code geschrieben wurden.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Ob Euro oder Cent kann man bei den Münzen und Scheinen übrigens am Wert festmachen, wenn man alle Werte in der gleichen Grössenordnung speichert.

Ungetestet:

Code: Alles auswählen

#!/usr/bin/env python3

DENOMINATIONEN = [
    ("Scheine", [50000, 20000, 10000, 5000, 2000, 1000, 500]),
    ("Stücke", [200, 100, 50, 20, 10, 5, 2, 1]),
]


def betrag_als_text(betrag):
    euro, cent = divmod(betrag, 100)
    return f"{euro} Euro und {cent} Cent"


def main():
    betrag = int(float(input("Geldbetrag: ")) * 100)
    print(f"Es müssen {betrag_als_text(betrag)} zurückgegeben werden.")
    for form, werte in DENOMINATIONEN:
        for wert in werte:
            anzahl, betrag = divmod(betrag, wert)
            divisor, art = (1, "Cent") if wert < 100 else (100, "Euro")
            print(
                f"{wert // divisor:3}-{art}-{form:<7}: {anzahl:2}"
                f" - Bleiben {betrag_als_text(betrag)}."
            )


if __name__ == "__main__":
    main()
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
senseye
User
Beiträge: 15
Registriert: Sonntag 12. September 2021, 23:00

@__blackjack__
Konnte mir schon denken, dass ich Variablen so nicht verändern kann, dachte aber es gibt vielleicht doch einen Weg.
Genau, wegen den drei fast gleich aussehenden for-Schleifen habe ich versucht es mit einer Funktion zu lösen.
Habe jetzt etwas gebraucht, um dein Besispiel zu verstehen, weiß jetzt aber wie Du vorgegangen bist.
divmod() kannte ich noch garnicht.

Danke für die Ausführliche Antwort, Problem gelöst.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Die Art würde ich auch noch in den Daten kodieren:

Code: Alles auswählen

#!/usr/bin/env python3

DENOMINATIONEN = [
    ("Euro-Scheine", 100, [500, 200, 100, 50, 20, 10, 5]),
    ("Euro-Stücke", 100, [2, 1]),
    ("Cent-Stücke", 1, [50, 20, 10, 5, 2, 1]),
]

def betrag_als_text(betrag):
    euro, cent = divmod(betrag, 100)
    return f"{euro} Euro und {cent} Cent"


def main():
    betrag = int(float(input("Geldbetrag: ")) * 100)
    print(f"Es müssen {betrag_als_text(betrag)} zurückgegeben werden.")
    for form, multiplicator, werte in DENOMINATIONEN:
        for wert in werte:
            anzahl, betrag = divmod(betrag, wert * multiplicator)
            print(
                f"{wert:3}-{form:<12}: {anzahl:2}"
                f" - Bleiben {betrag_als_text(betrag)}."
            )


if __name__ == "__main__":
    main()
Dann kann man das auch gut auf exotische Währungen umschreiben:

Code: Alles auswählen

#!/usr/bin/env python3

DENOMINATIONEN = [
    ("Dollar-Scheine", 100, [100, 50, 20, 10, 5, 2, 1]),
    ("Half-Dollar", 50, [1]),
    ("Quarter", 25, [1]),
    ("Dime", 10, [1]),
    ("Cent-Stücke", 1, [5, 1]),
]

def betrag_als_text(betrag):
    dollar, cent = divmod(betrag, 100)
    return f"{dollar} Dollar und {cent} Cent"


def main():
    betrag = int(float(input("Geldbetrag: ")) * 100)
    print(f"Es müssen {betrag_als_text(betrag)} zurückgegeben werden.")
    for form, multiplicator, werte in DENOMINATIONEN:
        for wert in werte:
            anzahl, betrag = divmod(betrag, wert * multiplicator)
            print(
                f"{wert:3}-{form:<12}: {anzahl:2}"
                f" - Bleiben {betrag_als_text(betrag)}."
            )
Antworten