Beginnerfrage...

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
peterwoodbridge
User
Beiträge: 50
Registriert: Freitag 30. November 2012, 10:26

Guten Tag
Ich beschäftige mich erst seit kurzem mit python. Gibt es ein Beginnerforum irgendwo? Gerne möchte ich, um die Codes besser zu verstehen, im Detail folgenden simplen Code durchspielen:

Code: Alles auswählen

n = [3,5,7]
def alpha(x):
	for i in range(0,len(x)):
		x[i] = x[i]*2
	return x
	
print alpha(n)
gibt mir den output [6,10,14].

Wenn ich nun den Code leicht abändere:

Code: Alles auswählen

n = [3,5,7]
def alpha(x):
	for i in range(0,len(x)):
		x[i] = x[i]*2
	        return x
	
print alpha(n)
bekomme ich [6, 5, 7]. Was bewirkt diese Indentation beim Return? Wieso wird im 1. Fall alle Elemente mit 2 multipliziert, im 2. Fall aber nur das Erste?

Code: Alles auswählen

n = [3,5,7]
def alpha(x):
	for i in range(0,len(x)):
		x[i] = x[i]*2
        return x[i]
	
print alpha(n)
nun bekomme ich als output nur noch den letzten Wert verdoppelt: 14... was bewirkt also das return x (wieso gibt mir dieser code nur noch 1 Wert als output)?

Ich hoffe, dass einer von euch kurz die Zeit nimmt und diese Fragen beantworten kann. Besten Dank.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Willkommen zu Python und im Forum!

Warum sollte dieses Forum denn nicht fuer Anfaenger geeignet sein?

Zum Code: Nun dieser Code wird nicht deine Beobachtung erzeugen, sondern eine Fehlermeldung. Ist die ``return``-Anweisung aber auf einer Einrueckungsebene mit `x ...`, dann gibt es nur einen Schleifendurchlauf, d.h. nur das erste Element der Liste wird verdoppelt.

Eine Programmiersprache durch zufaellige Aenderungen kennen zu lernen ist allerdings kein guter Ansatz. Lese mal die ersten paar Kapitel des Tutorials, hier werden die absoluten Grundlagen erklaert und man kann danach sinnvolle Aenderungen an Code machen _und_ sie verstehen ;)
peterwoodbridge
User
Beiträge: 50
Registriert: Freitag 30. November 2012, 10:26

Hi cofi
Besten Dank für die schnelle Antwort :o
Also Fehlermeldungen gab es keine. Es kann daran liegen, dass bei meinen codes hier diese Indentation nicht richtig dargestellt wurde.

kann ich also davon ausgehen, dass, sobald ein "return"-befehl erfolgt, die for-Schleife abgebrochen wird? Wenn der return ja eingerückt ist, dann ist dies nach 1 Element der Fall.

Dann frage ich mich aber, wieso beim return x das letzte Element verdoppelt wird UND nur dieses angezeigt wird.

Ich werde mich bei den tutorials schlau machen.

hier nochmals die 3 codes (evtl lags an TABs statt leerzeichen):

Code: Alles auswählen

n = [3,5,7]
def alpha(x):
   for i in range(0,len(x)):
      x[i] = x[i]*2
   return x
   
print alpha(n)

Code: Alles auswählen

n = [3,5,7]
def alpha(x):
   for i in range(0,len(x)):
        x[i] = x[i]*2
        return x
   
print alpha(n)

Code: Alles auswählen

n = [3,5,7]
def alpha(x):
	for i in range(0,len(x)):
		x[i] = x[i]*2    """8 leerzeichen davor"
	return x[i]    """4 leerzeichen davor"""
	
print alpha(n)
edit: auch jetzt wird der letzte code falsch dargestellt. bei mir gabs den output 14 :)
BlackJack

@peterwoodbridge: Zum Einrücken: 4 Leerzeichen pro Ebene ist bei Python Konvention. Tabs haben das Problem das nirgends festgelegt ist wie weit ein Tab einrückt. Da kann jeder seine eigenen Einstellungen beispielsweise im verwendeten Editor vornehmen, oder halt auch nicht wie hier im Forum oder in E-Mails, Terminalausgaben, und so weiter. Darum sollte man Leerzeichen verwenden. Und während der Compiler bei Python mit konsistent verwendeten Tabs klar kommt, auch wenn das in der Anzeige eventuell nicht sinnvoll eingerückt erscheint, bekommt er Probleme wenn man Tabs und Leerzeichen mischt. Dann kann es sein dass der Quelltext dort wo man ihn sich anzeigen lässt, zwar sinnvoll eingerückt erscheint, aber für den Compiler fehlerhaft aussieht, weil er andere Annahmen über Tabs macht, als die Software die den Quelltext anzeigt.

Mit dem Muster ``for index in range(len(sequence)):`` solltest Du übrigens sehr sparsam umgehen. In den allermeisten Fällen ist das in Python ein „anti pattern”. Man sollte das nur verwenden, wenn man tatsächlich nur den Index benötigt. Wenn man nur die Elemente benötigt kann man direkt über die Elemente der Sequenz iterieren. Wenn man zusätzlich zu den Elementen einen Index benötigt, kann man die `enumerate()`-Funktion verwenden. In diesem Beispiel kann man das so machen,
aber das ist im Grunde auch kein typischer Python-Code. Man würde eher eine neue Liste erstellen mit den verdoppelten Elementen, statt eine vorhandene zu verändern. Insbesondere wenn man da ein ``return`` so wie im ersten Beispiel stehen hat. Denn das ist so wie es jetzt da steht überflüssig und irreführend. Von einer Funktion die eine Datenstruktur verändert, erwartet man nicht dass sie diese Struktur auch noch mal zurück gibt. Der Aufrufer hat dieses Objekt ja schon.

Das nur so allgemein. Hier geht es im speziellen ja mehr um die Platzierung und Auswirkung von der ``return``-Anweisung auf den Programmablauf und nicht um sinnvolle Funktions-APIs.
peterwoodbridge
User
Beiträge: 50
Registriert: Freitag 30. November 2012, 10:26

Auch dir danke ich für den beitrag, blackjack :) nun weiss ich, dass ich absolut gar nichts weiss und einiges zu tun habe in den nächsten tagen/wochen/monaten...
mein Beispiel stammt von einer seite, wo man verschiedene aufgaben lösen muss... hab teilweise durch probieren diese lösen können, jedoch nicht immer die unterschiede verstanden, wenn gewisse Begriffe leicht abgeändert werden. Aber dass man direkt über Elemente indexieren kann, ist mir (natürlich) nicht bekannt und hätte auch keine Idee wie das geht.

wie hättest du denn das Ganze gemacht?
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Man indexiert nicht über eine Liste, man iteriert über diese ;-) Hier mal als kurze Beispiele:

Code: Alles auswählen

>>> spam = [2, 3, 4, 23, 42]
>>> for n in spam:
...     print n
... 
2
3
4
23
42
>>> for index, n in enumerate(spam):
...     print index, n
... 
0 2
1 3
2 4
3 23
4 42
>>> for index, n in enumerate(spam):
...     spam[index] = n**2
... 
>>> print spam
[4, 9, 16, 529, 1764]
>>> 
>>> eggs = [n*2 for n in spam]
>>> spam
[4, 9, 16, 529, 1764]
>>> eggs
[8, 18, 32, 1058, 3528]
Das Leben ist wie ein Tennisball.
BlackJack

@peterwoodbridge: Nicht „indexieren” sondern „iterieren”. Indexieren bedeutet den Indexoperator (``[…]``) anzuwenden also zum Beispiel ``sequence[42]`` und iterieren kommt von Iteration, also schrittweise etwas abarbeiten, zum beispielsweise in Schleifen und insbesondere in ``for``-Schleifen.

Im Grunde iterierst Du schon direkt über eine Sequenz, nämlich die Liste von Zahlen die von der `range()`-Funktion zurück gegeben wird. Und die benutzt Du dann als Index für `x`. Vielleicht wird es durch ein paar Beispiele in einer Python-Shell deutlicher:

Code: Alles auswählen

In [10]: values = [3, 5, 7]

In [11]: range(len(values))
Out[11]: [0, 1, 2]

In [12]: for i in range(len(values)):
   ....:     print i
   ....: 
0
1
2

In [13]: for i in range(len(values)):
   ....:     print values[i]
   ....: 
3
5
7

In [14]: for value in values:
   ....:     print value
   ....: 
3
5
7

In [15]: for i, value in enumerate(values):
   ....:     print i, value
   ....: 
0 3
1 5
2 7
Wie ich das gemacht hätte käme auf die Aufgabenstellung an. Ob man den Inhalt einer vorhandenen Liste verändern soll, oder eine neue Liste mit veränderten Werten liefern soll. Im ersten Fall hätte ich das im Grunde so gemacht wie Du, allerdings ohne das ``return`` am Ende. Und mit besseren Namen und `xrange()` statt `range()`.

Im anderen Fall muss man in der Funktion eine neue Liste erstellen und die mit den verdoppelten Werten füllen. Entweder in dem man eine leere Liste erstellt und die Werte mit der `append()`-Methode anfügt, oder mit einer speziellen Syntax um Listen zu erstellen, der sogenannten „list comprehension”.

Code: Alles auswählen

def values_doubled(values):
    for i in xrange(len(values)):
        values[i] *= 2
        # a *= b  <=>  a = a * b  (gilt in der Regel)


def double_values_a(values):
    result = list()
    for value in values:
        result.append(value * 2)
    return result


def double_values_b(values):
    return [value * 2 for value in values]  # <- List comprehension.
Edit: Verdammt ich war zu langsam. :-)
peterwoodbridge
User
Beiträge: 50
Registriert: Freitag 30. November 2012, 10:26

Hätte nicht gedacht, dass ihr euch die Mühe macht, so zu helfen :) Besten Dank.
Ich arbeite meine Beispiele anhand von codecademy.com durch, habe aber mitlerweile gegoogelt, dass dies wohl kein optimaler Einstieg ist... Dort müssen Aufgaben erfüllt werden (deswegen kenne ich die Funktion enumerate beispielsweise nicht). und am Ende resultiert dann ein schlechter Programmierstil :)
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

peterwoodbridge hat geschrieben:... und am Ende resultiert dann ein schlechter Programmierstil
In dieser Annahme sehe ich auch eine der großen Hürden, die es gerade Einsteigern schwer macht, den Überblick und die Motivation nicht zu verlieren. Ständig hat man das Gefühl, man könnte (oder noch schlimmer: sollte) etwas anderst (weil besser?) machen. Oft versteht man den vermeintlich besseren Ansatz überhaupt nicht und beim Versuch, diesen zu verstehen tauchen dann nicht selten noch weitere Fragezeichen oder Meinungen anderer auf.
Aus eigener Erfahrung (ich habe den tiefschwarzen Gürtel im Warumfragen!) kann ich nur den Rat geben, gut darauf zu achten, die Balance zwischen "ich möchte es doch 'richtig' machen" und "das kapier' ich nicht, muss ich jetzt aber auch (noch) nicht" zu wahren.
Hängt natürlich stark von der jeweiligen Persönlichkeit ab, ist jedenfalls für mich nach wie vor eine der großen Herausforderungen, um in diesem schier unendlichen Programmieruniversum nicht unterzugehen!

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Antworten