(Gelöst) List in For-Schleife ä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.
Gnushi
User
Beiträge: 77
Registriert: Dienstag 12. Dezember 2006, 09:49

(Gelöst) List in For-Schleife ändern

Beitragvon Gnushi » Samstag 20. Januar 2007, 16:04

Hallo zusammen!

Ich habe das Problem, daß ich auf möglichst pythonischem Wege mit einer For-Schleife eine Liste verändern möchte, also etwa so:

Code: Alles auswählen

Foo = ['a', 'b', 'c', 'd']
for i in Foo:
    i = i * 2
print Foo


Natürlich ergibt das keinen Sinn, das i ist ja nicht an die Liste Foo gebunden. Ich habe nun einmal die Möglichkeit, einen Index mitlaufen zu lassen:

Code: Alles auswählen

Idx = 0
for i in Foo:
    Foo[Idx] = i * 2
    Idx = Idx + 1
print Foo


oder eine neue Liste zu erzeugen:

Code: Alles auswählen

Bar = []
for i in Foo:
    Bar.append(i * 2)
Foo = Bar
print Foo


Beide Lösungen erfordern eine neue Variable, die erste Lösung sieht mir auch zu sehr nach einer für mich typischen Pascal-Lösung aus. Gibt es einen "direkteren" Weg, die Liste zu verändern?

Gnushi
Zuletzt geändert von Gnushi am Samstag 20. Januar 2007, 16:45, insgesamt 1-mal geändert.
EyDu
User
Beiträge: 4866
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Beitragvon EyDu » Samstag 20. Januar 2007, 16:11

Schau dir mal "map" und "list comprehension" an. Das ist zwar nicht direkt Ändern, aber erfüllt durchaus das, was du haben möchtest.

Code: Alles auswählen

def mul2(x):
    return x * 2

#Loesung 1
spam = [1,2,3,4]
eggs = map(mul2, spam)

#Loesung 2
eggs = map(lambda x: x*2, spam)

#Loesung 3 (mit list comprehension)
eggs = [x*2 for x in spam]
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Re: List in For-Schleife ändern

Beitragvon gerold » Samstag 20. Januar 2007, 16:15

Gnushi hat geschrieben:Index mitlaufen zu lassen

Hi Gnushi!

So z.B.:

Code: Alles auswählen

foo = ['a', 'b', 'c', 'd']

for index, item in enumerate(foo):
    foo[index] = item * 2
print foo

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Gnushi
User
Beiträge: 77
Registriert: Dienstag 12. Dezember 2006, 09:49

(Gelöst) List in For-Schleife ändern

Beitragvon Gnushi » Samstag 20. Januar 2007, 16:41

Hallo Leute!

@EyDu:
Das Realwelt-Problem erstreckt sich über 10 Zeilen, ich habe es hier nur etwas gekürz, um es verständlicher zu halten. Mit List-Comprehension komme ich leider insofern nicht weiter, als dass dann mein Code nicht mehr lesbar wäre. Für das geschilderte Problem finde ich die Lösung aber super!


@Gerold:
gerold hat geschrieben:So z.B.:

Code: Alles auswählen

for index, item in enumerate(foo):
    foo[index] = item * 2



Wow, ich wusste doch, dass es da etwas geben muss. Vielen Dank, das ist die Lösung für mich!

Gnushi
Benutzeravatar
Joghurt
User
Beiträge: 877
Registriert: Dienstag 15. Februar 2005, 15:07

Re: (Gelöst) List in For-Schleife ändern

Beitragvon Joghurt » Samstag 20. Januar 2007, 22:10

Gnushi hat geschrieben:Wow, ich wusste doch, dass es da etwas geben muss.
Der "pythonische" Weg wäre übrigens EyDus Lösung #3
BlackJack

Beitragvon BlackJack » Samstag 20. Januar 2007, 22:23

Gnushi meinte es ist etwas zu kompliziert für eine List-Comprehension. Trotzdem ist die List-Comprehension oder `map()` eventuell eine pythonischere Lösung weil man den 10-Zeilen-Quelltext in eine (lokale) Funktion stecken kann.
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Beitragvon sape » Samstag 20. Januar 2007, 22:29

Gnush, könntest du den 10-Zeiler Posten?
Gnushi
User
Beiträge: 77
Registriert: Dienstag 12. Dezember 2006, 09:49

Beitragvon Gnushi » Montag 22. Januar 2007, 21:29

sape hat geschrieben:Gnush, könntest du den 10-Zeiler Posten?


Gerne. Er sieht jetzt allerdings etwas anders aus, weil ich hinter ein Geheimnis von Python gekommen bin ;-)

(Ja, ich weiß ich bin noch Anfänger)

Habe ich nämlich:

Code: Alles auswählen

Foo = [1, 2]
Bar = [Foo, Foo, Foo]
print Bar
for x in Bar:
    x[0] = 7
print Bar

So wird die Liste geändert.

Habe ich hingegen

Code: Alles auswählen

Foo = 1
Bar = [Foo, Foo, Foo]
print Bar
for x in Bar:
    x = 7
print Bar

so werden die Elemente nicht verändert. Dies half mir dabei, folgenden Code zu verbessern, vom ursprünglichen Problem ist nichts mehr übrig:


Code: Alles auswählen

       for Ship in self.__Ships:
            Pos, Alive, Initialized, CounterClock = Ship
            PosX, PosY = Pos
            if PosY >= 0 and not Initialized:
                Screen.blit(EnemiesImg, Pos, EnemyBlackRect)
                UpdateRects.append((PosX, PosY, EnemyWidth, EnemyHeight))
                PosY = PosY + 2
                if CounterClock and PosY >= self.__Bottom2:
                    PosY = self.__Bottom2
                    Initialized = True
                elif not CounterClock and PosY >= self.__Bottom1:
                    PosY = self.__Bottom1
                    Initialized = True
                Pos = (PosX, PosY)
                Screen.blit(EnemiesImg, Pos, self.__ImgRect)
                UpdateRects.append((PosX, PosY, EnemyWidth, EnemyHeight))
            elif PosY < 0:
                PosY = PosY + 1
            else:
                NumInit = NumInit + 1
            Ship[0] = (PosX, PosY)
            Ship[2] = Initialized
        if NumInit == self.__Num:
            self.__MoveInit = False
        if len(UpdateRects) > 0:
            pygame.display.update (UpdateRects)


Bei diesem Code geht es darum, dass gerade feindliche Raumschiffe von oben den Bildschirm betreten und sich so positionieren, daß sie Captain Tux ( ;-) ) angreifen können. Dort, wo Ship[0]=(PosX, PosY) steht, bestand mein ursprüngliches Problem.

Liebe Grüße

Gnushi
BlackJack

Beitragvon BlackJack » Montag 22. Januar 2007, 23:41

Die Namen sind "unpythonisch", Du kamst von Pascal, oder? Python-Programmierer erwarten bei Namen in "MixedCase" Klassen.

Ausserdem sind da zu viele Unterstriche. Zwei führende Unterstriche sind eigentlich dazu gedacht um Namenskonflikte, z.B. bei MixIn-Klassen zu vermeiden, das ist kein "private"-Mechanismus. Wenn man ein Attribut als "privat" Kennzeichnen will, dann wird per Konvention ein einzelner Unterstrich verwendet um die öffentliche API von Implementierungsdetails unterscheiden zu können.

Es sieht so aus, als wenn `Ship` besser eine Klasse sein sollte. ``ship.position = (42, 23)`` ist viel aussagekräftiger als ``ship[0] = (42, 23)``

Einige Zeilen liessen sich mit ``+=`` etwas verkürzen, also z.B. ``pos_y += 1``.
Gnushi
User
Beiträge: 77
Registriert: Dienstag 12. Dezember 2006, 09:49

Beitragvon Gnushi » Dienstag 23. Januar 2007, 07:49

BlackJack hat geschrieben:Ausserdem sind da zu viele Unterstriche. Zwei führende Unterstriche sind eigentlich dazu gedacht um Namenskonflikte, z.B. bei MixIn-Klassen zu vermeiden, das ist kein "private"-Mechanismus. Wenn man ein Attribut als "privat" Kennzeichnen will, dann wird per Konvention ein einzelner Unterstrich verwendet um die öffentliche API von Implementierungsdetails unterscheiden zu können.


Siehe: http://docs.python.org/tut/node11.html#SECTION0011600000000000000000
Zitat:There is limited support for class-private identifiers. Any identifier of the form __spam (at least two leading underscores, at most one trailing underscore) is textually replaced with _classname__spam, where classname is the current class name with leading underscore(s) stripped. This mangling is done without regard to the syntactic position of the identifier, so it can be used to define class-private instance and class variables, methods, variables stored in globals, and even variables stored in instances.

Es sieht so aus, als wenn `Ship` besser eine Klasse sein sollte. ``ship.position = (42, 23)`` ist viel aussagekräftiger als ``ship[0] = (42, 23)``


Stimmt.

Gnushi
BlackJack

Beitragvon BlackJack » Dienstag 23. Januar 2007, 08:10

Gnushi hat geschrieben:
BlackJack hat geschrieben:Ausserdem sind da zu viele Unterstriche. Zwei führende Unterstriche sind eigentlich dazu gedacht um Namenskonflikte, z.B. bei MixIn-Klassen zu vermeiden, das ist kein "private"-Mechanismus. Wenn man ein Attribut als "privat" Kennzeichnen will, dann wird per Konvention ein einzelner Unterstrich verwendet um die öffentliche API von Implementierungsdetails unterscheiden zu können.


Siehe: http://docs.python.org/tut/node11.html#SECTION0011600000000000000000
Zitat:There is limited support for class-private identifiers. Any identifier of the form __spam (at least two leading underscores, at most one trailing underscore) is textually replaced with _classname__spam, where classname is the current class name with leading underscore(s) stripped. This mangling is done without regard to the syntactic position of the identifier, so it can be used to define class-private instance and class variables, methods, variables stored in globals, and even variables stored in instances.


Interessant dass das so im Tutorial steht und kein Wort von der "Ein-Unterstrich-Konvention". Ich bleibe trotzdem dabei: wenn man alles "private" macht, ist man noch nicht in Python angekommen. Der Tutorialtext erklärt aber, warum so oft mit Newbies in comp.lang.python darüber diskutiert werden muss. :-(
Gnushi
User
Beiträge: 77
Registriert: Dienstag 12. Dezember 2006, 09:49

Beitragvon Gnushi » Dienstag 23. Januar 2007, 09:27

BlackJack hat geschrieben:Interessant dass das so im Tutorial steht und kein Wort von der "Ein-Unterstrich-Konvention".


In der Referenz-Doku finde ich auch nichts von einem einzelnen Unterstrich. Siehe: http://docs.python.org/ref/atom-identifiers.html

Vielleicht kannst Du eine vertrauenswürdige Quelle für diese "Ein-Unterstrich-Konvention" nennen?

Liebe Grüße

Gnushi

Edit:
Habe etwas gefunden: http://www.python.org/dev/peps/pep-0008/:
_single_leading_underscore: weak "internal use" indicator. E.g. "from M
import *" does not import objects whose name starts with an underscore.

und später:
Use one leading underscore only for non-public methods and instance
variables.
Zuletzt geändert von Gnushi am Dienstag 23. Januar 2007, 09:43, insgesamt 1-mal geändert.
Benutzeravatar
Joghurt
User
Beiträge: 877
Registriert: Dienstag 15. Februar 2005, 15:07

Beitragvon Joghurt » Dienstag 23. Januar 2007, 09:42

PEP 8
_single_leading_underscore: weak "internal use" indicator. E.g. "from M
import *" does not import objects whose name starts with an underscore.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Beitragvon gerold » Dienstag 23. Januar 2007, 09:59

Gnushi hat geschrieben:In der Referenz-Doku finde ich auch nichts von einem einzelnen Unterstrich. Siehe: http://docs.python.org/ref/atom-identifiers.html

Hi Gnushi!

Da wurde geschlampt! Python-Programmierern wird allgemein etwas mehr Selbstverantwortung zugetraut. Deshalb genügt es auch, wenn man durch "einen" Unterstrich andeutet, dass es sich hier um etwas handelt, auf das man nicht direkt zugreifen sollte -- außer man weiß was man tut. Die Verwendung von zwei Unterstrichen ist eine Verschärfung. Diese deutet dem Python-Programmierer an, dass er/sie auf keinen Fall direkt darauf zugreifen soll, denn er/sie weiß wahrscheinlich doch nicht so schnell was er/sie tut, da hier noch ein paar, nicht sofort durchschaubare, magische Dinge im Spiel sind.

_foo = Greif nicht direkt darauf zu, außer du weißt was du tust.
__bar = Es hat in keinem Fall Sinn, direkt darauf zuzugreifen, versuch es erst gar nicht.

Übertreibe es nicht mit den zwei Unterstrichen. Kennzeichne deine Attribute nur dann mit "__", wenn es wirklich notwendig ist und der Schutz des Attributes durch zwei Unterstriche wirklich gerechtfertigt ist. Normalerweise sollte es genügen, einen Unterstrich zur Kennzeichnung zu verwenden. Wir Python-Programmierer wissen dann schon, dass man nicht direkt darauf zugreifen soll.

- http://www.python.org/doc/essays/styleguide/#names
- http://www.python.org/doc/essays/ppt/hp ... sld023.htm
- http://www.python-forum.de/post-54587.html#54587 :-)

Ich hoffe, dass ich es halbwegs erklären konnte.

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs

Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Beitragvon sape » Dienstag 23. Januar 2007, 15:27

Full Ack.

lg

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder