Konstrukt unklar

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
chevallier
User
Beiträge: 22
Registriert: Sonntag 3. Mai 2015, 16:26

Hallo,

Es geht um folgenden Code:

Code: Alles auswählen

searchdir="."
for path,dirs,files in os.walk(searchdir):
	# Bestimmte Ordner überspringen:
	dirs[:]=[dir for dir in sorted(dirs) if not dir in ['ordnername', 'tmp']]
	for file in sorted(files):
		newname=os.path.join(path,file)
		print(newname)
Ich verstehe die 4te Zeile nicht. Kann sie mir bitte jemand erklären, oder sagen, wo ich Information zu diesem Konstrukt erhalte?
Vielen Dank.
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

@chevallier: das ist eine ListComprehension. Die Zeile insgesamt bewirkt, dass die Verzeichnisse in sortierter Reihenfolge durchgegangen und "ordnername" und "tmp" übersprungen werden.
Man hätte es auch als

Code: Alles auswählen

dirs[:] = sorted(set(dirs) - {"ordnername", "tmp"})
schreiben können.
chevallier
User
Beiträge: 22
Registriert: Sonntag 3. Mai 2015, 16:26

Hallo,

Danke für die Antwort.

Mir sind List Comprehensions jetzt weitesgehend klar, nur verstehe ich dieses Kontrukt nicht (Zeile 4):

Code: Alles auswählen

import string
from random import * 
characters = string.ascii_letters + string.punctuation  + string.digits
password =  "".join(choice(characters) for x in range(randint(8, 16)))
Es ist mir vollkommen klar, was hier passiert, nur die Syntax bringt mich durcheinander und zwar genauer dieser Teil:
>>> choice(characters) for x in range(randint(8, 16)) <<<
choice(characters) hat nämlich keinen Bezug zu der Variablen "x", für mich jedenfalls nicht. Ich dachte der Wert, der in der Liste Comprehension als erstes steht muss auch nach dem "for" in einer Art und Weise auftauchen, so dass er mit dem ersten Wert verknüpft ist, bzw. dieser in Bezug zu ihm steht. Wenn ich zB.
>>> choice(characters) 9<<< schreibe, erhalte ich eine Fehlermeldung.

Anscheinend muss man dieses Konstrukt auswendig lernen und hinnehmen, dass es so ist. Aber ich versuche halt lieber zu verstehen was hier passiert. Vielleicht kann mir jemand sagen, wie man das noch schreiben könnte, damit ich verstehe wie das Kontrukt tickt.

Ich wäre sehr dankbar, wenn mir jemand diese Syntax erklären kann.

Viele Grüße.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Das ist keine List Comprehension, sondern eine Generator Expression. Die funktionieren genauso wie LCs nur schreibt man sie mit runden statt eckigen Klammern und sie erzeugen Generatoren keine Listen.

Zusaetzlich haben sie noch den Sonderfall, dass wenn sie das einzige Argument eines Funktionsaufrufes sind man die (extra) Klammern weglassen kann.

Zusammenfassend:

Code: Alles auswählen

 # als LC
password =  "".join([choice(characters) for x in range(randint(8, 16))])
# mit den extra klammern
password =  "".join((choice(characters) for x in range(randint(8, 16))))
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Und noch zum ``x``: Pythonischer wäre es hier, statt dem Namen ``x`` einen Unterstrich zu nehmen:

Code: Alles auswählen

"".join(choice(characters) for _ in range(randint(8, 16)))
Das ``x`` wird hier ja tatsächlich nicht gebraucht, da der ``range`` Ausdruck lediglich für eine bestimmte (zufällige) Anzahl an Durchläufen sorgt. Die Laufvariable selber wird für das Ergebnis nicht gebraucht. Ein "konkreter" Name verwirrt hier eben mehr, als dass er hilft - am ``_`` erkennt ein geübter Pythonista sofort, dass es auf diesen Namen und damit auf das Objekt dahinter im weiteren Verlauf nicht ankommt.

Drum merke Dir allgemein gültig: Genau an solchen Stellen sollte man per Konvention ``_`` als Namen wählen!
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

@chevallier: Oder noch einmal anders: Niemand zwingt einen den Wert der Laufvariable auch tatsächlich zu nutzen, weder bei „list comprehensions“, noch bei Generatorausdrücken, und auch nicht bei ganz normalen ``for``-Schleifen. Aber syntaktisch muss da halt etwas stehen damit das als das jeweilige Konstrukt als solches erkannt werden kann.

Normalerweise wird der Wert benutzt, nicht weil man dazu gezwungen würde, sondern weil es Sinn macht, weil man einen Ausdruck oder Block in einer Schleife, LC, Generatorausdruck ja für jeden Einzelwert einer Sequenz oder eines anderen iterierbaren Objekts ausführen möchte. Nur in dem Fall wo es ausschliesslich um die wiederholte Ausführung geht kann es halt vorkommen das ma nicht an dem Wert sondern nur an der Wiederholung interessiert ist.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Warum eigentlich ``dirs[:] = ...``? Den einzigen Sinn, den ich dahinter sehen kann ist, dass der GC dadurch keine Arbeit hat. Aber macht das Sinn, wenn das der einzige Sinn ist?

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

@mutetella: Weil man damit die Rekursion von `os.walk` einschraenkt:
https://docs.python.org/2/library/os.html#os.walk hat geschrieben:When topdown is True, the caller can modify the dirnames list in-place (perhaps using del or slice assignment), and walk() will only recurse into the subdirectories whose names remain in dirnames; this can be used to prune the search, impose a specific order of visiting, or even to inform walk() about directories the caller creates or renames before it resumes walk() again. Modifying dirnames when topdown is False is ineffective, because in bottom-up mode the directories in dirnames are generated before dirpath itself is generated.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

For dem Fragen Doku lesen! Wie oft ich diese Lektion wohl noch lernen muss... :oops:

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