2016-09-11 4 views
0

Ich lese gerade Python Crash Course von Eric Matthes und ich habe eine unglaublich schwierige Zeit, Kapitel 8 zu verstehen, die sich nur um Funktionen handelt. Ich stehe bei Übung 8-10 fest, die mich auffordert, eine neue Funktion zu verwenden, um eine Liste zu ändern, die in der vorherigen Übung verwendet wurde. HierVerwirrt über das Ändern von Listen mit zwei Funktionen in Python

ist die Übung:

8-9. Magicians: Make a list of magician's names. Pass the list to a function called show_magicians(), which prints the name of each magician in the list. 

8-10. Great Magicians: Start with a copy of your program from exercise 8-9. Write a function make_great() that modifies the list of magicians by adding the phrase the great to each magician's name. Call show_magicians() to see that the list has actually been modified. 

Hier ist mein Code für 8-9:

def show_magicians(names): 
    """Print each magician name""" 
    for name in names: 
     msg = name.title() 
     print(msg) 

magician_names = ['sonic', 'tails', 'knuckles'] 
show_magicians(magician_names) 

ich ein sehr ähnliches Thema auf dieser Website gesehen habe und so habe ich versucht, Verwenden Sie den Code in der ersten Antwort auf dieser Seite, um mir zu helfen: Python crash course 8-10

Allerdings scheint mein Code weiterhin als der Compiler p falsch zu sein Nach jedem Namen "3 Mal".

Hier ist der aktuelle Code, den ich für 8-10 verwendet

def show_magicians(names): 
    """Print each magician name""" 
    for name in names: 
     msg = name.title() 
     print(msg) 

magician_names = ['sonic', 'tails', 'knuckles'] 
show_magicians(magician_names) 

def make_great(list_magicians): 
    """Add 'Great' to each name.""" 
    for magician_name in magician_names: 
     for i in range(len(list_magicians)): 
      list_magicians[i] += " the great!" 

make_great(magician_names) 
show_magicians(magician_names) 

Ich weiß nicht, warum, aber es scheint nur, dass ich habe aus diesem ganzen Kapitel von Funktionen zu kämpfen durch. Hat jemand zufällig irgendwelche empfohlenen Tutorials, um einen Blick darauf zu werfen, um mir zu helfen, Funktionen besser zu verstehen? Vielen Dank für Ihre Zeit.

+0

Sorry, aber das Problem ist die Doppel-Loop: für magician_name in magician_names: for i in range (len (list_magicians)): Sie nur die zweite – user2539336

+0

benötigen In ' '' make_great() '' 'Sie haben geschachtelt für Schleifen - wie oft läuft die * innere * Schleife? – wwii

+0

Wie Sie aus meiner Antwort in der verknüpften Frage sehen können, wurde nur eine Schleife verwendet. Du benutzt zwei. – Li357

Antwort

2

Ok, so dass Sie eine zusätzliche Schleife auf der Außenseite haben, entfernen Sie das. Der endgültige Code:

def show_magicians(names): 
    """Print each magician name""" 
    for name in names: 
     msg = name.title() 
     print(msg) 

magician_names = ['sonic', 'tails', 'knuckles'] 
show_magicians(magician_names) 

def make_great(list_magicians): 
    """Add 'Great' to each name.""" 
    for index, item in enumerate(list_magicians): 
     list_magicians[index] += " the great!" 

make_great(magician_names) 
show_magicians(magician_names) 

Sie taten ein for-in zusammen mit einem for-in range. Dadurch wurde der Code zum Anhängen der Zeichenfolge wiederholt. Lassen Sie mich erklären, was Ihre vorherigen Programm tat:

Erläuterung: Bei jeder Iteration Sie mit einem for-in geschlungen, es in einer Schleife um die innere Schleife 3 mal verursacht. Also, eine jede Iteration der äußeren Schleife, würde es die innere Schleife dreimal wiederholen, so dass es the great 3 mal an jeden Namen anhängen.

Auch, als der Beantworter der verknüpften Frage, würde ich lieber Sie verwenden enumerate über range(len(list_magicians)).

+0

Anstatt nur eine refaktorierte Antwort zu geben, sollten Sie versuchen zu demonstrieren, was falsch war und warum - vielleicht mit einigen zusätzlichen Druckanweisungen. – wwii

+0

Ihr 'make_great' wird nichts anderes tun, als seinen Parameter zu modifizieren und dann den geänderten Parameter bei der Rückgabe zu verwerfen. Sie müssen den geänderten Parameter zurückgeben, damit der Aufrufer ihn verwenden kann. Ich vermute, dass dies der Grund dafür war, dass das OP mit einer verschachtelten Schleife endete. Die Version, die nur "list_magicians" geändert hat, hat nichts bewirkt (genauer gesagt, etwas getan und dann verworfen), so dass das OP eine weitere Schleife hinzugefügt hat, die sich explizit auf die globale Variable "magician_names" auswirkte. –

+0

@ D-Von Was genau meinst du mit * 'Parameter ändern' *? Der Code funktioniert gut, da ich kein 'for-in' verwende, das den Wert einfach in eine neue Variable kopiert. Dies * ändert * die globale Liste. – Li357

1

Ändern Sie die zweite Methode:

def make_great(list_magicians): 
    """Add 'Great' to each name.""" 
    i = 0 
    for magician_name in magician_names: 
     list_magicians[i] += " the great!" 
     i += 1 

Zur Zeit zweimal Sie Looping mit zwei for loops so dass es 3 mal hinzugefügt werden!

+1

mitgeholfen habe, stimme ich zu, dass dies korrekt funktioniert, aber es hat zwei stilistische Probleme. Erstens ignoriert die Funktion ihren Parameter, was verwirrend ist. Zweitens modifiziert die Funktion direkt 'magician_names', was außerhalb des Gültigkeitsbereichs der Funktion liegt. –

+0

Einverstanden, diese Antwort wird funktionieren, aber Sie haben Recht. –

+0

@D-Von 'magician_names' liegt nicht außerhalb des Gültigkeitsbereichs der Funktion. 'magician_names' ist global, aber ich stimme zu, dass diese Funktion in vielerlei Hinsicht verwirrend ist. – Li357

1

Schauen wir uns Ihre make_great Funktion:

def make_great(list_magicians): 
    """Add 'Great' to each name.""" 
    for magician_name in magician_names: 
     for i in range(len(list_magicians)): 
      list_magicians[i] += " the great!" 

Was macht das?

for magician_name in magician_names: Schleifen durch magician_names.

for i in range(len(list_magicians)): Loops durch list_magicians nach Index.

list_magicians[i] += " the great!" Fügt the great! zum i te Element von list_magicians

Welche Codezeile ist nicht notwendig?

for magician_name in magician_names: Durchschleifen bietet keine Verwendung. Da seine Länge 3 ist, erhalten Sie für jedes Element 3 the great! s. Entfernen Sie diese Codezeile, und die Funktion sollte ordnungsgemäß funktionieren.

+0

Nach dem Entfernen der äußeren for-Schleife wird die Funktion nichts tun, weil sie nur ihren Parameter ändert und dann die Änderungen verwerfen. Sie müssen eine Rückkehr hinzufügen. Dies ist wahrscheinlich, wie das OP mit der verschachtelten Schleife endete: die innere Schleife allein "hat nichts getan", also fügte er die äußere Schleife hinzu. –

+0

@ D-Von: In seinem Code ruft er 'make_great()' auf, ohne das Ergebnis seiner Namensliste zuzuordnen, also wollte er die Liste wahrscheinlich ändern. –

+0

Es ist nicht klar, dass er den Unterschied zwischen dem Ändern der Liste an Ort und Stelle und dem Ändern einer Kopie der Liste versteht. Ich vermute, das ist der Grund für seine Verwirrung über Funktionen. Aber ich stimme zu, dass sein ursprünglicher Code die Liste geändert hat. Wie bereits von @Andrew L. oben erwähnt wurde, ist mein Kommentar tatsächlich inkorrekt, da die Liste als Referenz und nicht als Kopie übergeben wird. Ich habe meine Antwort bearbeitet, um dies zu reflektieren. Bitte ignorieren Sie meinen Kommentar zu Ihrer Antwort! Ich bin geneigt, es zu löschen, wenn Stack Overflow mich lässt. –

1

Wie ein anderer Beantworter sagte, machen Ihre verschachtelten Schleifen im Prinzip die gleiche Sache, aber für jedes Mal, wenn die äußere Schleife läuft, läuft die innere Schleife. Beide Schleifen versuchen, über die Liste der Magier zu iterieren, wobei einer den Namen verwendet, den die Liste außerhalb der Funktion (magician_names) passiert, und einer den Namen verwendet, den die Liste innerhalb der Funktion (list_magicians) durchläuft. So oder so würde es funktionieren, aber beides ist zu viel. Von diesem Standpunkt aus ist Ihr Missverständnis nicht von Funktionen, sondern von Schleifen.

Aber die Tatsache, dass Sie magician_names in der Funktion überhaupt erwähnen, zeigt ein Missverständnis. Es wird funktionieren, aber es ist eine schlechte Form. In der Regel sollte sich der Code einer Funktion ausschließlich auf Namen beziehen, die über die Parameter an die Funktion übergeben werden. In diesem Fall sollten Sie die Schleife über magician_names verwerfen und die Schleife über list_magician halten. Es gibt Ausnahmen von der Regel, aber Sie sollten einen bestimmten Grund im Kopf haben, bevor Sie es brechen. Die Rechtfertigung für die Regel ist die Verkapselung: Sie können die Funktion vollständig verstehen, indem Sie ihre Parameterliste und ihren Code lesen, ohne nach der Rolle von irgendetwas außerhalb der Funktion fragen zu müssen.

Wenn Sie die Idee akzeptieren, dass Funktionen nur auf ihren Parametern funktionieren sollten, dann müssen Sie fragen: Wie wirkt sich eine Funktion auf die Außenwelt aus? Eine Antwort ist, dass die Funktion return etwas ist, und die Außenwelt tut freiwillig etwas mit dem, was zurückgegeben wurde. Eine andere Antwort ist, dass der Parameter der Funktion zufällig auf ein Objekt in der Außenwelt zeigt, so dass das Ändern des Objekts innerhalb der Funktion es automatisch außerhalb der Funktion ändert. Ich bevorzuge den ersten Weg, aber in deinem Fall ist es wahrscheinlich einfacher, den zweiten zu verwenden. Also, wenn Sie magician_names in Ihre Funktion übergeben, benennt Python es in list_magicians um; Sie arbeiten an list_magicians innerhalb der Funktion, so ändert sich magician_names auch außerhalb der Funktion; Sie kehren von der Funktion zurück und der Namelist_magicians geht weg, aber die Änderungen zu magician_names überleben.

Hier ist ein letzter Ratschlag, der Ihr Wissen auf "list comprehensions" erweitert, ein Thema, von dem Sie wahrscheinlich noch nichts gelernt haben (aber sie sind perfekt für diese Anwendung): Ich empfehle eine funktionierende Funktion zu schreiben ein einzelnes Datenstück, das dann diese Funktion wiederholt aufruft, anstatt zu versuchen, sowohl die Wiederholung als auch die Einzelstück-Datenmodifikation in der gleichen Funktion durchzuführen. Gefällt mir:

def append_great(magician): 
    return magician + " the Great" 

Mit dieser Funktion zur Verfügung, ein Listenverständnis sieht ganz nett aus. Es verarbeitet eine Liste Element für Element gemäß Ihren Anweisungen. Wie folgt:

>>> magicians = [ "Houdini", "Fubini" ] 
>>> [ append_great(m) for m in magicians ] 
['Houdini the Great', 'Fubini the Great'] 

Beachten Sie, dass das Listenverständnis eine neue Liste zurückgegeben hat; magicians bleibt unverändert, es sei denn, Sie ändern es selbst. So sollten die Dinge sein. Funktionen sollten nicht die Außenwelt erreichen (außer es gibt einen wirklich guten Grund); Stattdessen sollte die Außenwelt der Funktion einige Daten geben, das Ergebnis erhalten und das Ergebnis so verwenden, wie es die Außenwelt am besten weiß.Das ist mein Eintreten für die Rückkehr zur Wertschätzung der Außenwelt, aber wie gesagt, in diesem Fall ist es einfacher, den Pass-a-Reference-Weg zu benutzen. keine Empfehlung für eine Ressource haben

+0

Vielen Dank für Ihre ausführliche Antwort. Um ehrlich zu sein, habe ich eine schwierige Zeit damit, alles zu verstehen, was du eingegeben hast, wahrscheinlich weil es spät ist und ich müde bin, aber ich werde deine Antwort morgen noch einmal anschauen und sie auf meinen aktuellen Code anwenden erhalten Sie eine bessere Vorstellung davon, wie Looping funktioniert. :) – PhantomDiclonius