a.append(a[i]+a[j]) - eine Anfängerfrage

Code-Stücke können hier veröffentlicht werden.
Antworten
Tyrax
User
Beiträge: 73
Registriert: Mittwoch 4. Februar 2009, 18:31

Hallo Gemeinde,

ich bin ein blutiger Programmier- und ibs. Python-Anfänger und habe ein kleines Skript geschrieben, das - wie zB bei der Fibonacci-Folge - ein neues Listenelement aus den beiden vorangegangenen erzeugt. Die Listeneinträge sind Ganzzahlen. Mit

a = [1, 1]
a.append(a+a[j])

klappt es aber nicht. Python interpretiert meine Liste

[1, 1]

als

[(1,), (1,)]

und produziert dementsprechend eine Liste von Tupeln. Was kann ich tun?

Danke und Grüße, Tyrax

P.S.: Ich poste auch gerne das ganze Skript, wenn's hilft.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Tyrax hat geschrieben:P.S.: Ich poste auch gerne das ganze Skript, wenn's hilft.
Würde es.
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Wenn deine Liste aus Tupeln mit einem Element besteht müsste das funktionieren:

Code: Alles auswählen

a.append((a[i][0]+a[j][0],))
BlackJack

@Tyrax: Ich sehe da kein Problem:

Code: Alles auswählen

In [5]: a = [1, 1]

In [6]: a.append(a[i] + a[j])

In [7]: a
Out[7]: [1, 1, 2]
Ich könnte mir vorstellen, dass das nicht funktioniert, wenn `i` und `j` nicht an die richtigen Werte gebunden sind, aber wie da *Tupel* heraus kommen können, verstehe ich absolut nicht.

Wobei man statt `i` und `j` hier auch Konstante Zahlen einsetzen kann. Sind ja immer die gleichen Werte, nämlich der Index für's vorletzte und für's vorvorletzte Element.
Tyrax
User
Beiträge: 73
Registriert: Mittwoch 4. Februar 2009, 18:31

Hallo,

danke erstmal. Erstaunlicherweise habe ich den Fehler nun selbst gefunden. Ich hatte zwei verirrte Kommata (siehe Code), die aus der Eingabe von a0 und a1 Tupel gemacht haben. Ich hatte die Zeilen erst an anderer Stelle und sie dann kopiert - mit Kommata. Sowas kommt von sowas.

Code: Alles auswählen

print("""Dieses Programm berechnet die Fibonacci-Folge zu deinen Startwerten \n und gibt die Folge bis zu einem von dir gewählten Zähler an.\n""")
a0 = int(input("Geben sie das erste Element ihrer Fibonacci-Folge an: a0 =")) # Hier hatte ich ein Komma
a1 = int(input("Geben sie das zweite Element ihrer Fibonacci-Folge an: a1 =")) # Hier auch
n  = int(input("Bis zu welchem Folgenglied soll die Folge berechnet werden? n ="))
i = 0  #
liste = [a0 , a1] #
# Zunächst definiere ich die Funktion und sage welche Variable sie verwendet:
def Fibonaccischritt():
      global liste, i
      liste.append(liste[i] + liste[i+1])
      i = i + 1
      return liste  #i # Eine Funktion läuft unabhängig vom restlichen Programm.
#                        Werte, mit denen noch gearbeitet werden soll, müssen daher mit "return" gesondert ausgegeben werden.
while i < n:
  Fibonaccischritt()
print(liste)
Über Kommentare und Verbesserungsvorschläge freue ich mich jederzeit.

Aber wie gesagt, nun klappt's. Danke und Grüße, Tyrax
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Warum machst du "liste" global?
Und "i" kannst du dir dank negativer indexierung sparen.

Code: Alles auswählen

liste.append(liste[-2] + liste[-1])
BlackJack

Insbesondere stimmt der Kommentar mit dem "unabhängig" nicht, wenn man externe Objekte verändert. Für `liste` ist ``global`` sogar unnötig, weil das Objekt verändert wird, aber nicht der Name neu gebunden wird. Auf ``global`` sollte man so gut wie immer verzichten. Werte sollte Funktionen als Argumente betreten und als Rückgabewerte verlassen.

Wenn man die Anzahl der Schleifendurchläufe schon vor Eintritt in die Schleife kennt, verwendet man besser eine ``for``-Schleife. Dann spart man sich den expliziten Text, die Initialisierung des Zählers vor der Schleife und das manuelle hochzählen innerhalb der Schleife.
Tyrax
User
Beiträge: 73
Registriert: Mittwoch 4. Februar 2009, 18:31

Hallo audax und BlackJack,

danke für die Hinweise. Der Kommentar zu "return" sollte eigentlich nicht hier rein, aber so lerne ich immerhin was dazu.

@audax: Die negative Indizierung hatte ich nicht von Anfang an, daher das i. Ich benutze es aber auch noch für die while-Schleife. Wenn ich, wie BlackJack vorschlägt, eine for-Schleife nehme, kann ich das i aber tatsächlich rausschmeißen. Deinen Link muss ich noch genauer angucken.

Grüße, Tyrax
Tyrax
User
Beiträge: 73
Registriert: Mittwoch 4. Februar 2009, 18:31

Hallo nochmal,

hier der Code mit den vorgeschlagenen Verbesserungen (ist jetzt auch viel kürzer):

Code: Alles auswählen

print("""Dieses Programm berechnet die Fibonacci-Folge zu deinen Startwerten \n und gibt die Folge bis zu einem von dir gewählten Zähler an.\n""")
a1 = int(input("Geben sie das erste Element ihrer Fibonacci-Folge an: a1 ="))
a2 = int(input("Geben sie das zweite Element ihrer Fibonacci-Folge an: a2 ="))
n  = int(input("Bis zu welchem Folgenglied soll die Folge berechnet werden? n ="))
liste = [a1 , a2] #
def Fibonaccischritt():
      liste.append(liste[-1] + liste[-2])
for i in range(2,n):
  Fibonaccischritt()
print(liste)
Noch weitere Kommentare? Sonst wende ich mich mal dem nächsten Projekt zu. Grüße, Tyrax
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Pack es gleich in eine Funktion, der "Fibonaccischritt" ist vollkommen überflüssig und du wirst die globale Liste los:

Code: Alles auswählen

def fibonacci(a, b, n):
    result = [a, b]
    for i in range(len(result), n):
        result.append(result[-1]+result[-2])
    return result[:n]
Tyrax
User
Beiträge: 73
Registriert: Mittwoch 4. Februar 2009, 18:31

EyDu,

das ist in der Tat besser. Ich nehme an, du hast len(result) benutzt um klarzustellen, warum da (in diesem Fall) 'ne Zwei steht. Mit Benutzereingabe und Ausgabe der Liste sieht's bei mir jetzt so aus:

Code: Alles auswählen

def fibonacci(a1, a2, n):
    liste = [a1, a2]
    for i in range(len(liste), n):
        liste.append(liste[-1]+liste[-2])
    print(liste)
a1 = int(input("a1 ="))
a2 = int(input("a2 ="))
n  = int(input("n ="))
fibonacci(a1, a2, n)
Ich habe die return-Zeile rausgenommen. Die brauche ich nur, wenn ich danach noch mit "liste" arbeiten will, oder?

Grüße, Tyrax
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

Schreib in Zeile 5 lieber das return hin und in Zeile 9 kommt das print zum Ausgeben. So ist Logik und Ausgabe besser voneinander getrennt.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

`print' ist - wenn du noch nicht Python 3 benutzt - noch keine Funktion, also lass die Klammern weg. Hier macht das keinen großen Unterschied, da das damit nicht zum Tuple wird, aber man sollte sich das gar nicht erst falsch angewöhnen ;) (Selbst wenn man dann auf Python 3 wechselt, ist es falsch angewöhnt ;) )
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

cofi hat geschrieben:wenn du noch nicht Python 3 benutzt
Was aber wohl der Fall ist, denn das ``int(input(...))`` wäre ja in 2.x eher unsinnig und die generelle 3.0-konformheit lässt mich schließen, dass der Code für 3.0 gedacht ist.
Antworten