mir unerklärliche Zuweisung

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
kodela
User
Beiträge: 185
Registriert: Montag 12. Oktober 2015, 21:24
Wohnort: Landsberg am Lech
Kontaktdaten:

Hallo,

bin gerade dabei, mich in die Geheimnisse von Python einzuarbeiten. Sagt jetzt bitte keiner, da gäbe es keine Geheimnisse. Das ist sicher richtig, aber für mich gibt es eben welche.

Für mein erstes Modul habe ich nach Beispielen gesucht und bin dabei auf diese Seite gestoßen. Dort findet sich folgender Code für die Berechnung einer Fibonacci-Folge:

Code: Alles auswählen

def fib(n): # gib die Fibonacci-Folge zurück bis n
    result = []
    a, b = 0, 1
    while b < n:
        result.append(b)
        a, b = b, a+b
    return result
Was bewirkt der Code in den Zeilen 3 und 6, also a, b = 0, 1 und a, b = b, a+b ?

Nach der Initialisierung in Zeile 3 ist a == 0 und b == 1. Warum wurde b der Wert 1 zugewiesen? Weil das die erste Fibonacci-Zahl ist, aber die Zuweisung sieht doch anders aus.

Ähnlich geht es in Zeile 6 weiter, in b sind die Fibonacci-Zahlen und in a die jeweils vorhergehende Fibonacci-Zahl.

Trotz allem Suchens habe ich für diese Art der Zuweisung nichts gefunden, bin mir aber sicher dass es irgend wo erklärt ist.

Kann mir bitte jemand auf die Sprünge helfen?

MfG, kodela
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@kodela: das nennt sich "tuple unpacking", es wird ein Tuple b, a+b erzeugt und in die beiden Variablen a und b entpackt.
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Zu dem, was Sirius3 schin geschrieben hat: der Komma-Operator bindet stärker, als der Zuweisungsoperator. Wenn man die Klammerung explizit macht, sieht man besser, was passiert:

Code: Alles auswählen

In [1]: (a, b) = (0, 1)

In [2]: (a, b) = (b, a + b)

In [3]: a, b
Out[3]: (1, 1)
Der Komma-Operator dient dazu, Tupel zu erzeugen:

Code: Alles auswählen

n [4]: xs = 1,

In [5]: xs
Out[5]: (1,)

In [6]: xs[0]
Out[6]: 1

In [7]: x, = xs

In [8]: x
Out[8]: 1
Die Klammern braucht man nur zur Disambiguierung. In dem Fibonacci-Programm wurden sie weggelassen, weil da nichts zweideutig ist.
In specifications, Murphy's Law supersedes Ohm's.
kodela
User
Beiträge: 185
Registriert: Montag 12. Oktober 2015, 21:24
Wohnort: Landsberg am Lech
Kontaktdaten:

@Sirius3
@pillmuncher

Danke vorab. Das muss ich aber erst verdauen. Melde mich dann wieder.

MfG, kodela

PS:

Der Hinweis mit der Klammerung hat gezündet. Nochmals vielen Dank!
kodela
User
Beiträge: 185
Registriert: Montag 12. Oktober 2015, 21:24
Wohnort: Landsberg am Lech
Kontaktdaten:

Hallo,

hier eine Zusammenfassung:

Das Konstrukt a, b = 0, 1 steht für einen Tupel mit den beiden Werten a und b, wobei a mit 0 und b mit 1 initialisiert werden.

Besser ist dies mit Klammern zu erkennen: (a, b) = (0, 1)

In der Schleife wird bei jedem Durchlauf mit (a, b) = (b, a + b) der Wert b in a übernommen und der ursprüngliche Wert von a wird zu b aufaddiert.

Würde man a und b als eigenständige Variable definieren, müsste man bei der Anpassung in der Schleife a temporär zwischenspeichern. Das sähe dann so aus:

Code: Alles auswählen

# Initiqalisierung
a = 0
b = 1

# Anpassung in der Schleife
t = a
a = b
b += t
Durch die Zusammenfassung von a und b in einem Tupel erübrigt sich eine Zwischenspeicherung, der Code ist kompakter und sicherlich auch eleganter.

Nochmals vielen Dank für Eure Aufklärung.

MfG, kodela
Benutzeravatar
bwbg
User
Beiträge: 407
Registriert: Mittwoch 23. Januar 2008, 13:35

kodela hat geschrieben:[...]
Das Konstrukt a, b = 0, 1 steht für einen Tupel mit den beiden Werten a und b, wobei a mit 0 und b mit 1 initialisiert werden.
[...]
Genaugenommen erzeugt die rechte Seite der Zuweisung das tuple und die linke Seite nimmt dieses wieder auseinander (unpacking). Das funktioniert nicht nur mit tuples sondern mit jeder Sequenz (tuples, lists, iterators, ...). Wichtig ist, dass die linke Seite der Zuweisung alle Elemente abdecken kann.

Häufig findet man beim unpacking einen Unterstrich/underscore (_). Im Grunde eine normale Zuweisung. _ ist ein gültiger Name, signalisiert jedoch, dass man diesen Wert nicht benötigt:

Code: Alles auswählen

>>> _, two, _ = range(1, 4)
>>> two
2
>>> _
3
"Du bist der Messias! Und ich muss es wissen, denn ich bin schon einigen gefolgt!"
Antworten