[Python]Bombers Fragetread

BomberDeluxe schrieb:
Ok, ich wusste nicht, dass a immer neu zugewiesen wird.
Ist a hier eigentlich eine globale Variable, weil sie ja zum ersten mal außerhalb der Funktion definiert werden muss?
a ist lokal, da er in der Parameterliste deklariert wird. Und a wird immer neu zugewiesen, da der Funktionsaufruf immer geschieht.
BomberDeluxe schrieb:
Warum wird printf immer ausgeführt? Eigentlich müsste es doch nur am Ende ausgegeben werden, weil vorher ja immer gleich die Funktion wieder von vorn aufgerufen wird, und sie so gar nicht zum ende kommt.
Weil es die normale Abfolge ist. Dein Vorhaben würde geschehen, würdest du printf() in den else-Zweig setzen, da nur dort a <= 0 ist. Im Beispiel wird es aber auch ausgegeben, trotz dass a > 0 ist. Nur c() wird aufgerufen, wenn a > 0 ist.
 
Gut, jetzt hab ich das verstanden.

Jetzt zu dem Programm:

Erstmal in deutsch:

Code:
funktion rekursion[pfad]
i=0
Tue solange bis a leer
wenn datei = ordner
dann return rekursion [pfad+Ordnername]
ansonsten umbenennen in i und i++
return rekursion
aber ich glaub da sind einige fehler drin...
So, hab ich mir das vorgestellt. Ich weiß, dass das jetzt ziemlich bescheuert klingt. Aber meine Frage, würde das so funktionieren, also nach diesem Prinzip in Python?
 
Nein, du rufst rekursion immer auf, wodurch du irgendwann einen Stapelüberlauf (Stack Overflow) bekommst.
Code:
function rename( Pfad )
{
	PfadInhalt = Pfad.DateienUndOrdnerLesen();
	for( i = 0; i < PfadInhalt.length(); i++ )
	{
		if( PfadInhalt[i] ist Datei ) DateiUmbenennen( PfadInhalt[i], i );
		else if( PfadInhalt[i] ist Ordner ) [B]rename( Pfad + PfadInhalt[i] );[/B]
	}
}
 
Das klappt aber auch nicht. Hier ist es ja so, dass wenn du dich jetzt im Unterordner befindest und dort alle dateien umbenannt wurden nicht mehr in den Hauptordner zurückkehrst und dich um den nächsten ordner dort kümmerst, oder?
 
Ich glaube du solltest erst einmal drüber schlafen, vielleicht verstehst du es morgen. ;) Du scheiterst nämlich immer genau an dem Punkt, an dem das Grundprinzip der Rekursion zu verstehen ist.

Wenn im letzten Beispiel alle Dateien in einem Ordner umbenannt sind, kehrt das Programm nicht zum ursprünglichen/ersten rename()-Aufruf zurück, sondern zum letzten, der bereits viele Ordner tief ins Dateisystem vorgedrungen sein kann. Dadurch steckst du im rename() im rename() im rename().... und wenn die letzte, tiefste Stufe erreicht ist und die Umbenennung dort stattfand, dann wird mit der nächsthöheren Stufe weitergemacht, d.h. du befindest dich immer noch in der rename(), nur an einem anderen Ort im Dateisystem.

P.S.: wenn du nebenbei noch mit CSS kämpfst (siehe dein anderer Thread), dann kannst du dich doch auf dein Python-Problem ohnehin nicht konzentrieren.
 
Zuletzt bearbeitet:
BomberDeluxe schrieb:
Code:
def walk(level):
    if level > 10:
        return level
 
    return walk(level + 1)
 
print walk(0)

Was genau macht das return?

Es liefert den Rückgabewert der Funktion walk.


BomberDeluxe schrieb:
Lässt es einfach die Funktion/Variable/usw. nochmal ausführen?

Der Rückgabewert ist das Ergebnis eines rekursiven Aufrufs, ja. Mit jedem Aufruf ändert sich das Funktionsargument. Das geschieht so lange, bis eine bestimmte Bedingung erfüllt ist. Dann ruft die Funktion nicht mehr sich selbst auf, sondern liefert das Funktionsargument zurück. Visuell gedacht: Genau so wie sich vorher die Funktion bei jedem Aufruf immer weiter verschachtelt hat, wandert dieser Wert jetzt durch alle Ebenen zurück, bis er am Ende beim allerersten Aufruf ankommt und ausgegeben wird.


BomberDeluxe schrieb:
Auch hier die gleichen Fragen wie oben:
Ist level eine globale Variable?

Nein, ein Funktionsargument. Mit Funktionen hast Du Dich doch bereits beschäftigt?


BomberDeluxe schrieb:
Warum wird print immer ausgeführt? Es normalerweise dürfte es ja nur am Ende ausgeführt werden, weil durch das return die Funktion immer von neuem beginnt, bis der print befehl bearbeitet werden kann.

Die print-Anweisung ist nicht Teil der Funktion! Beachte die Python-Regeln hinsichtlich der Code-Einrückung! Diese Anweisung wird einmal ausgeführt und gibt den Wert eines Funktionsaufrufs aus.
 
Das macht er doch. Geh die Abfolge doch mal auf dem Papier an einem Beispiel durch. Mal ausgehend von meinem Borderlands Verzeichnis (natürlich gekürzt):
Code:
+---Binaries
|   |   ALF.DLL
|   |   binkw32.dll
|   |   Borderlands.exe
|   |   Borderlands.ico
|   |   cudart.dll
|   |   dbghelp.dll
|   |   DFA.dll
|   |   DFA_left.bmp
|   |   DFA_top.bmp
|   |   fmodex.dll
|   |   
|   +---DLCSetup
|   |       Alf.dll
|   |       DFA.dll
|   |       DFA_left.bmp
|   |       DFA_top.bmp
|   |       DLCSetup.exe
|   |       lang_dfa.ini
|   |       setup.ref
|   |       
|   +---PhysXLocal
|   |       PhysXLoader.dll
|   |       
|   +---Windows
|   |   |   WindowsTools.dll
|   |   |   
|   |   \---WPF
|   |       |   PreferencesWindow.xaml
|   |       |   PreferencesWindowStyles.xaml
|   |       |   
|   |       \---Resources
|   |               ContentBrowserDefs.xaml
|   |               ContentBrowserStyles.xaml
|   |               PreferencesWindow_En-US.xaml
|   |               UnrealEdCSharp_En-US.xaml
|   |               
|   +---wxRC
|   |       GearRemoteControl.xrc
|   |       UnrealEd.xrc
|   |       UnrealEdPhysics.xrc
|   |       
|   \---wxRes
|           Align_Bottom.bmp
|           Align_Center_Horizontal.bmp
|           Align_Center_Vertical.bmp
|           Align_Left.bmp
|           
+---Engine
|   +---Config
|   |       BaseBuildInfo.ini
|   |       BaseCompat.ini
|   |       BaseEditor.ini
|   |       
|   +---Localization
|   |           
|   \---Shaders
|           AmbientOcclusionMeshShaders.usf
|           AmbientOcclusionShader.usf
|           BasePassPixelShader.usf
|           
+---EULA
|       2K_EULA_ENGLISH.rtf
|       2K_EULA_FRENCH.rtf
|       2K_EULA_GERMAN.rtf
|       
+---Readme
|       Readme_DEU.txt
|       Readme_ENG.txt

Code:
rename( "Borderlands" );

Binaries -> Ordner -> rename( "Borderlands\Binaries" )
        DLCSetup -> Ordner -> rename( "Borderlands\Binaries\DLCSetup" )
            Alf.dll -> Datei -> umbenennen( "Alf.dll", 0 )
            DFA.dll -> Datei -> umbenennen( "DFA.dll", 1 )
            DFA_left.bmp -> Datei -> umbenennen( "DFA_left.bmp", 2 )
            DFA_top.bmp -> Datei -> umbenennen( "DFA_top.bmp", 3 )
            DLCSetup.exe -> Datei -> umbenennen( "DLCSetup.exe", 4 )
            lang_dfa.ini -> Datei -> umbenennen( "lang_dfa.ini", 5 )
            setup.ref -> Datei -> umbenennen( "setup.ref", 6 )
        PhysXLocal -> Ordner -> rename( "Borderlands\Binaries\PhysXLocal" )
            PhysXLoader.dll -> Datei -> umbenennen( "PhysXLoader.dll", 0 )
        Windows -> Ordner -> rename( "Borderlands\Binaries\Windows" )
            WPF -> Ordner -> rename( "Borderlands\Binaries\Windows\WPF" )
                Resources -> Ordner -> rename( "Borderlands\Binaries\Windows\Resources" )
                    ContentBrowserDefs.xaml -> Datei -> umbenennen( "ContentBrowserDefs.xaml", 0 )
                    ContentBrowserStyles.xaml -> Datei -> umbenennen( "ContentBrowserStyles.xaml", 1 )
                    PreferencesWindow_En-US.xaml -> Datei -> umbenennen( "PreferencesWindow_En-US.xaml", 2 )
                    UnrealEdCSharp_En-US.xaml -> Datei -> umbenennen( "UnrealEdCSharp_En-US.xaml", 3 )
        ...
Engine -> Ordner -> rename( "Borderlands\Engine" )
    ...
 
Also. Ich habe jetzt das meiste verstanden. Hier ist mein Quelltext, um alle Dateien in jedem Unterordner, und auch im Hauptordner umzubenennen.
Code:
def dateien(pfad):
	liste = os.listdir("C:/Dokumente und Einstellungen/User/Desktop/a")
	i=1
	for name1 in liste:
		j=str(i)
		name= "C:/Dokumente und Einstellungen/User/Desktop/a/" + name1
		if os.path.isfile(name):
			os.path.splitext(name)
			os.rename(name, pfad + j + os.path.splitext(name)[1])
			print (name+" wurde umbenannt.")
			i = i + 1
		elif os.path.isdir(name):
			return dateien(pfad+name1)
			print("Durchsuche Ordner " + name1)
		else: print (name+ " konnte nicht umbenannt werden")
	print ("Umbenennen erfolgreich")
Pfad wurde vorher als "C:/Dokumente und Einstellungen/User/Desktop/a/" gesetzt. Leider hat das nicht ganz geklappt und ich hatte einen Overflow. Wo könnte der Fehler sein?
 
Du verarbeitest immer den selben Pfad:

Code:
liste = os.listdir("C:/Dokumente und Einstellungen/User/Desktop/a")
 
Die Rekursion wird irgendwie nicht richtig durchgeführt. Er macht einen Ordner ordentlich durch, aber geht dann nicht mehr zurück.
Code:
def dateien(pfad):
	i=1
	for name1 in os.listdir(pfad):
		j=str(i)
		name= pfad + name1
		if os.path.isfile(name):
			os.path.splitext(name)
			os.rename(name, pfad + j + os.path.splitext(name)[1])
			print (name+" wurde umbenannt.")
			i = i + 1
		elif os.path.isdir(name):
			print("Durchsuche Ordner " + name1)
			return dateien(pfad+name1+"/")
		else: print (name+ " konnte nicht umbenannt werden")
	print ("Umbenennen erfolgreich")
 
Zuletzt bearbeitet:
Anscheinend hast du das alles immer noch nicht ganz verstanden, aber es wird schon.

Das return in Zeile 13 verursacht natuerlich den Abbruch der Funktion, sobald der erste Ordner gefunden wurde. Mach das return raus.

Ausserdem ist Zeile 7 unnoetig und zum konkatenieren von Pfaden solltest du os.path.join() verwenden.
 
Zuletzt bearbeitet:
Ich dachte return ist der ausführbefehl...
wo zeile 7 herkommt... keine Ahnung :P

was ist der unterschied zwischen meinem befehl und os.path.join()?
 
Wenn return der "Ausführbefehl" wäre, warum schreibst du dann "print(...)" statt "return print(...)"?

return verlaesst eine Funktion und gibt dabei das, was dahinter steht, zurueck.

Mit os.path.join musst du dir die Pfade halt nicht selbst zusammenfrickeln, was fehleranfaellig ist. Siehe Doku. os.path.normpath kannst du dir da auch gleich mal anschauen.
 
Sehr gut. Es läuft jetzt alles sehr gut. Bloß ein Problem habe ich noch. Jedes Mal, wenn ein neuer Ordner betreten wird, wird i wieder auf 1 gesetzt. Das will ich aber gerade nicht, ich will, dass i immer weitergezählt wird.
Wie kann ich das machen? Selbst wenn ich es als Parameter zur Funktion hinzufüge klappt es nicht... weil die funktion ja immer wieder neu aufgerufen wird und somit i immer = 1 gesetzt wird.
 
Nieman, aber ich muss i ja irgendwie definieren.
 
Code:
def dateien(pfad, i = 1):
	liste = os.listdir("C:/Dokumente und Einstellungen/User/Desktop/a")
	for name1 in liste:
		j=str(i)
		name= "C:/Dokumente und Einstellungen/User/Desktop/a/" + name1
		if os.path.isfile(name):
			os.path.splitext(name)
			os.rename(name, pfad + j + os.path.splitext(name)[1])
			print (name+" wurde umbenannt.")
			i = i + 1
		elif os.path.isdir(name):
			i = dateien(pfad+name1, i + 1) + 1
			print("Durchsuche Ordner " + name1)
		else: print (name+ " konnte nicht umbenannt werden")
	print ("Umbenennen erfolgreich")
	return i
 
soares schrieb:

Ja, und wie soll ich es sonst machen? :rolleyes:


Yuuri schrieb:
Code:
def dateien(pfad, i = 1):
	liste = os.listdir("C:/Dokumente und Einstellungen/User/Desktop/a")
	for name1 in liste:
		j=str(i)
		name= "C:/Dokumente und Einstellungen/User/Desktop/a/" + name1
		if os.path.isfile(name):
			os.path.splitext(name)
			os.rename(name, pfad + j + os.path.splitext(name)[1])
			print (name+" wurde umbenannt.")
			i = i + 1
		elif os.path.isdir(name):
			i = dateien(pfad+name1, i + 1) + 1
			print("Durchsuche Ordner " + name1)
		else: print (name+ " konnte nicht umbenannt werden")
	print ("Umbenennen erfolgreich")
	return i

Klappt nicht...
Ich hab mir auch ein paar gedanken gemacht und das kam raus:
Code:
def dateien(pfad):
	for name1 in os.listdir(pfad):
		j=str(i)
		name= pfad + name1
		if os.path.isfile(name):
			os.rename(name, pfad + j + os.path.splitext(name)[1])
			print (name+" wurde umbenannt.")
			i = i + 1
		elif os.path.isdir(name):
			print("Durchsuche Ordner " + name1)
			dateien(pfad+name1+"/")
		else: print (name+ " konnte nicht umbenannt werden")
	print ("Umbenennen erfolgreich")

In jedem Ordner sind 3 Dateien und ein weiterer Ordner, bis zum Ordner 1.1.1.
Im Ordner 1 werden die files von 1-3 umbenannt. Im Ordner 1.1 von 4-6 im Ordner 1.1.1 von 7-9. Soweit gut. Dann aber gibt es im Ordner 1 noch einen zweiten Ordner 1.2. Dort sind auch 3 Dateien drin, die jetzt auch wie die dateien im Ordner 1.1 von 4-6 benannt werden. Versteht ihr was ich meine?
 
Zuletzt bearbeitet:
BomberDeluxe schrieb:
Ja, und wie soll ich es sonst machen? :rolleyes:

Überlegen, welche Möglichkeiten Du hast und die naheliegende auswählen?

Wenn wir Dir hier alles vorkauen, ist der Erkenntnisgewinn geringer, als wenn Du selbst auf eine Lösung kommst. Es ist bei dem Problem nicht so, als ob Du auf einen völlig neuen Dreh kommen müsstest.
 
Zurück
Oben