Python Script zum ändern von Dateiendungen

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.
korkak
User
Beiträge: 29
Registriert: Freitag 30. Dezember 2011, 19:44

So!

ich habs geschafft und es funktioniert :D

ich poste den code mal hier, dann hat man quasi eine ende zu ende betrachtung wie sich alles entwickelt hat, wenn das ok ist für euch.

PyQt4 habe ich benutzt, zum ausprobieren braucht ihr glaube ich den inhalt folgender beiden dateien.

das programm habe ich rename_programm.py genannt:

Code: Alles auswählen

import os, glob, sys
from PyQt4 import QtGui, QtCore 
from rename import Ui_Hauptdialog as Dlg
class MeinDialog(QtGui.QDialog, Dlg):
    
    def __init__(self): 
        QtGui.QDialog.__init__(self) 
        self.setupUi(self)
        # Slots einrichten 
        self.connect(self.Eingabe, 
                QtCore.SIGNAL("clicked()"), self.onEingabe) 
        self.connect(self.Los, 
                QtCore.SIGNAL("clicked()"), self.onLos)
        self.connect(self.Loeschen, 
                QtCore.SIGNAL("clicked()"), self.onLoeschen)
        self.connect(self.Ende, 
                QtCore.SIGNAL("clicked()"), self.onEnde)
        
    def onEingabe(self): 
        # Daten auslesen 
        d = {}
        p = unicode(self.pfad.text())
        #self.ausgabe.append(p)
        if not os.path.exists(p):
            self.ausgabe.append("Das Verzeichnis '%s' existiert nicht." % p)
        alt = unicode(self.alt.text())
        global names
        names = glob.glob(os.path.join(p, "*." + alt))
        self.ausgabe.append("Folgende Dateien wurden gefunden:")
        self.ausgabe.append("-----------------------------------------------")
        self.ausgabe.append("\n".join(names))
        self.ausgabe.append("-----------------------------------------------")

    def onLoeschen(self):
        self.pfad.clear()
        self.alt.clear()
        self.neu.clear()
        
    def onLos(self):
        #self.ausgabe.append("Es geht Los!")
        neu = unicode(self.neu.text())
        for x in names:
            os.rename(x, os.path.splitext(x)[0]+'.'+neu)
        self.ausgabe.append("-----------------------------------------------")
        self.ausgabe.append("%d Dateien wurden umbenannt." % len(names))

    def onEnde(self): 
        self.close()

app = QtGui.QApplication(sys.argv) 
dialog = MeinDialog() 
dialog.show() 
sys.exit(app.exec_())

und hier der inhalt der rename.py datei:

Code: Alles auswählen

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'C:\Users\Schmidt\Desktop\Python\GUI\QT\rename.ui'
#
# Created: Fri Jan 20 13:07:15 2012
#      by: PyQt4 UI code generator 4.9
#
# WARNING! All changes made in this file will be lost!

from PyQt4 import QtCore, QtGui

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    _fromUtf8 = lambda s: s

class Ui_Hauptdialog(object):
    def setupUi(self, Hauptdialog):
        Hauptdialog.setObjectName(_fromUtf8("Hauptdialog"))
        Hauptdialog.resize(500, 649)
        self.groupBox = QtGui.QGroupBox(Hauptdialog)
        self.groupBox.setGeometry(QtCore.QRect(50, 30, 401, 271))
        self.groupBox.setObjectName(_fromUtf8("groupBox"))
        self.Eingabe = QtGui.QPushButton(self.groupBox)
        self.Eingabe.setGeometry(QtCore.QRect(150, 210, 93, 28))
        self.Eingabe.setObjectName(_fromUtf8("Eingabe"))
        self.Los = QtGui.QPushButton(self.groupBox)
        self.Los.setGeometry(QtCore.QRect(270, 210, 93, 28))
        self.Los.setObjectName(_fromUtf8("Los"))
        self.Loeschen = QtGui.QPushButton(self.groupBox)
        self.Loeschen.setGeometry(QtCore.QRect(150, 150, 211, 28))
        self.Loeschen.setObjectName(_fromUtf8("Loeschen"))
        self.widget = QtGui.QWidget(self.groupBox)
        self.widget.setGeometry(QtCore.QRect(70, 30, 291, 121))
        self.widget.setObjectName(_fromUtf8("widget"))
        self.gridLayout = QtGui.QGridLayout(self.widget)
        self.gridLayout.setMargin(0)
        self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
        self.label = QtGui.QLabel(self.widget)
        self.label.setObjectName(_fromUtf8("label"))
        self.gridLayout.addWidget(self.label, 0, 0, 1, 1)
        self.pfad = QtGui.QLineEdit(self.widget)
        self.pfad.setObjectName(_fromUtf8("pfad"))
        self.gridLayout.addWidget(self.pfad, 0, 1, 1, 1)
        self.label_2 = QtGui.QLabel(self.widget)
        self.label_2.setObjectName(_fromUtf8("label_2"))
        self.gridLayout.addWidget(self.label_2, 1, 0, 1, 1)
        self.alt = QtGui.QLineEdit(self.widget)
        self.alt.setObjectName(_fromUtf8("alt"))
        self.gridLayout.addWidget(self.alt, 1, 1, 1, 1)
        self.label_3 = QtGui.QLabel(self.widget)
        self.label_3.setObjectName(_fromUtf8("label_3"))
        self.gridLayout.addWidget(self.label_3, 2, 0, 1, 1)
        self.neu = QtGui.QLineEdit(self.widget)
        self.neu.setObjectName(_fromUtf8("neu"))
        self.gridLayout.addWidget(self.neu, 2, 1, 1, 1)
        self.ausgabe = QtGui.QTextEdit(Hauptdialog)
        self.ausgabe.setGeometry(QtCore.QRect(50, 320, 401, 251))
        self.ausgabe.setObjectName(_fromUtf8("ausgabe"))
        self.Ende = QtGui.QPushButton(Hauptdialog)
        self.Ende.setGeometry(QtCore.QRect(360, 600, 93, 28))
        self.Ende.setObjectName(_fromUtf8("Ende"))

        self.retranslateUi(Hauptdialog)
        QtCore.QMetaObject.connectSlotsByName(Hauptdialog)

    def retranslateUi(self, Hauptdialog):
        Hauptdialog.setWindowTitle(QtGui.QApplication.translate("Hauptdialog", "Dialog", None, QtGui.QApplication.UnicodeUTF8))
        self.groupBox.setTitle(QtGui.QApplication.translate("Hauptdialog", "Angaben", None, QtGui.QApplication.UnicodeUTF8))
        self.Eingabe.setText(QtGui.QApplication.translate("Hauptdialog", "Übernehmen", None, QtGui.QApplication.UnicodeUTF8))
        self.Los.setText(QtGui.QApplication.translate("Hauptdialog", "Umbenennen", None, QtGui.QApplication.UnicodeUTF8))
        self.Loeschen.setText(QtGui.QApplication.translate("Hauptdialog", "Eingabefelder löschen", None, QtGui.QApplication.UnicodeUTF8))
        self.label.setText(QtGui.QApplication.translate("Hauptdialog", "Pfad:", None, QtGui.QApplication.UnicodeUTF8))
        self.label_2.setText(QtGui.QApplication.translate("Hauptdialog", "Endung alt:", None, QtGui.QApplication.UnicodeUTF8))
        self.label_3.setText(QtGui.QApplication.translate("Hauptdialog", "Endung neu:", None, QtGui.QApplication.UnicodeUTF8))
        self.Ende.setText(QtGui.QApplication.translate("Hauptdialog", "Beenden", None, QtGui.QApplication.UnicodeUTF8))

Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Wenn Du `PyQt4` benutzt, dann könntest Du auch das `uic`-modul nutzen, um die GUI dynamisch zu erzeugen (das manuelle Erzeugen Deiner UI-Klasse fällt dann weg - genau das sprach Leonidas im letzten Posting davor an ;-) ).

Ich habe es mir nicht direkt angeguckt, aber wenn Du einen länger andauernden Prozess hast, bei dem Du Update-Nachrichten ausgeben willst in der GUI, dann kommst Du eigentlich nicht um das Thema "Threading" herum. lunar und ich haben mal ein kleines Beispiel für solche Interaktionen entwickelt¹. Evtl. guckst Du Dir das mal an...

Du benutzt die alte Semantik für SIGNALS und SLOTS. Wieso nutzt Du nicht die neue?

Code: Alles auswählen

# alt:
self.connect(self.Eingabe, QtCore.SIGNAL("clicked()"), self.onEingabe)
# neu
self.Eingabe.clicked.connect(self.onEingabe)
Dann sehe ich immer noch so unsägliche Namen wie `x`, `d` oder `p`. Speziell beim `x` wundert man sich:

Code: Alles auswählen

for x in names:
    # do something with `x`
Das schreit doch gerade nach:

Code: Alles auswählen

for name in names:
    # do sth. with `name`
Nimmst Du `x` nur, weil es kürzer zu tippen ist? Wenn ja, solltest Du das nicht tun, sondern stets einem aussagekräftigeren Namen den Vorzug geben.

Dann sah ich ein `global` im Code - das ist eigentlich immer unnütz und ein Zeichen für schlechtes Design.

Ich habe Deinen Anwendungsfall nicht mehr im Kopf, aber sich sehe da keine separate Logik-Funktion(en), für die eigentliche "Aufgabe". Ich hätte jetzt erwartet, dass Du Deinen bisherigen Code als Modul importierst und dann aus der GUI die entsprechenden Funktionen aufrufst.

¹Also ich hatte das ursprünglich mal demonstriert und lunar hat es - wie immer - in sinnvoller Weise verbessert ;-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
korkak
User
Beiträge: 29
Registriert: Freitag 30. Dezember 2011, 19:44

hey hyperion,

danke für deine kommentare.
wie gesagt ich bin blutiger anfänger und mache das alles zum ersten mal. ich glaube mir fehlt noch einiges an wissen um all deine ratschläge zu verstehen und umzusetzen :wink:

1) `uic`-modul
sagt mir nix, werd ich mir ansehen.

2) "Threading"
sagt mir nix, werd ich mir ansehen.

3) alte Semantik für SIGNALS und SLOTS
sieht gut aus werd ich sofort umsetzen :)

4) "aussagekräftigeren Namen"
werd ich mir zu herzen nehmen!

5) `global` im Code
ich wusste mir nicht anders zu helfen, in einer funktion setze und benutze ich die variable und in einer weiteren brauche ich genau diese variable wieder, wie soll ich es anders machen?

6) " bisherigen Code als Modul importierst"
das hatte ich auch vor aber dann hab ich mit dem designer rumgespielt und dann sah alles irgendwie etwas anders aus und so hab ich es dann halt so gemacht :K

ps: ich war echt happy als es am ende funktioniert hat 8)
Zuletzt geändert von korkak am Freitag 20. Januar 2012, 17:56, insgesamt 1-mal geändert.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

korkak hat geschrieben: 5) `global` im Code
ich wusste mir nicht anders zu helfen, in einer funktion setze und benutze ich die variable und in einer weiteren brauche ich genau diese variable wieder, wie soll ich es anders machen?
Indem Du das Objekt als Attribut zu Deiner Klasse hinzufügst z.B. Ich denke solche "Schwächen" in Sachen OOP sind mit der Grund, wieso viele hier einem Anfänger davon abraten, sich mit GUIs zu befassen.
korkak hat geschrieben: 6) " bisherigen Code als Modul importierst"
das hatte ich auch vor aber dann hab ich mit dem designer rumgespielt und dann sah alles irgendwie etwas anders aus und so hab ich es dann halt so gemacht :K
Hu? Was hat denn der Designer damit zu tun? :K
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
korkak
User
Beiträge: 29
Registriert: Freitag 30. Dezember 2011, 19:44

Hyperion hat geschrieben:
korkak hat geschrieben: 5) `global` im Code
ich wusste mir nicht anders zu helfen, in einer funktion setze und benutze ich die variable und in einer weiteren brauche ich genau diese variable wieder, wie soll ich es anders machen?
Indem Du das Objekt als Attribut zu Deiner Klasse hinzufügst z.B. Ich denke solche "Schwächen" in Sachen OOP sind mit der Grund, wieso viele hier einem Anfänger davon abraten, sich mit GUIs zu befassen.

ich mache es ja just for fun, die motivation warum ich jetzt schon etwas mit der gui gemacht habe war, dass ich einmal sehen wollte wie das ganze von anfang bis ende aussieht, als nächstes werde ich mich weiter in python einlesen.
hast du vielleicht ein beispiel für mich, wie ich das objekt als attribut einer klasse hinzufüge?
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

korkak hat geschrieben:
Hyperion hat geschrieben: hast du vielleicht ein beispiel für mich, wie ich das objekt als attribut einer klasse hinzufüge?
Na, ganz einfach so eben:

Code: Alles auswählen

In [21]: class Foo(object):
   ....:     
   ....:     def __init__(self):
   ....:         self.bar = []
   ....:         
   ....:         

In [22]: f = Foo()

In [23]: f.bar
Out[23]: []

In [24]: f.bar = range(10)

In [25]: f.bar
Out[25]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Du hast doch sogar eine Liste, oder?
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
korkak
User
Beiträge: 29
Registriert: Freitag 30. Dezember 2011, 19:44

da bin ich wieder hyperion,

folgende tipps von dir habe ich versucht umzusetzen:

- uic-modul eingebaut.

- neue Semantik für SIGNALS und SLOTS eingebaut.

- aussagekräftigere Namen eingebaut.

- "Threading", versucht einzubauen, aber wohl nicht korrekt. fällt mir wirklich schwer umzusetzen, falls möglich gib mir bitte ein beispiel wie ich es richtig einbaue :cry:

- als nächstes versuche ich dann die globale variable rauszunehmen.

Code: Alles auswählen

import os, glob, sys, threading
from PyQt4 import QtGui, QtCore, uic

class MeinDialog(QtGui.QDialog):
    
    def __init__(self):
        QtGui.QDialog.__init__(self)
        self.ui = uic.loadUi("rename.ui", self)
        # Slots einrichten
        self.Eingabe.clicked.connect(self.onEingabe)
        self.Los.clicked.connect(self.onLos)
        self.Loeschen.clicked.connect(self.onLoeschen)
        self.Ende.clicked.connect(self.onEnde)
        
    def onEingabe(self): 
        # Daten auslesen 
        d = {}
        pfad = unicode(self.pfad.text())
        if not os.path.exists(pfad):
            self.ausgabe.append("Das Verzeichnis '%s' existiert nicht." % pfad)
        alt = unicode(self.alt.text())
        global names
        names = glob.glob(os.path.join(pfad, "*." + alt))
        self.ausgabe.append("Folgende Dateien wurden gefunden:")
        self.ausgabe.append("-----------------------------------------------")
        self.ausgabe.append("\n".join(names))
        self.ausgabe.append("-----------------------------------------------")

    def onLoeschen(self):
        self.pfad.clear()
        self.alt.clear()
        self.neu.clear()
        
    def onLos(self):
        neu = unicode(self.neu.text())
        for name in names:
            MeinDialog.lock.acquire()
            os.rename(name, os.path.splitext(name)[0]+'.'+neu)
            MeinDialog.lock.release()
        self.ausgabe.append("-----------------------------------------------")
        self.ausgabe.append("%d Dateien wurden umbenannt." % len(names))

    def onEnde(self): 
        self.close()
 
    lock = threading.Lock()

    onEingabe_thread = threading.Thread(target = onEingabe)
    onLoeschen_thread = threading.Thread(target = onLoeschen)
    onLos_thread = threading.Thread(target = onLos)
    onEnde_thread = threading.Thread(target = onEnde)

    onEingabe_thread.start()
    onLoeschen_thread.start()
    onLos_thread.start()
    onEnde_thread.start()

    onEingabe_thread.join()
    onLoeschen_thread.join()
    onLos_thread.join()
    onEnde_thread.join()

app = QtGui.QApplication(sys.argv) 
dialog = MeinDialog() 
dialog.show() 
sys.exit(app.exec_())
korkak
User
Beiträge: 29
Registriert: Freitag 30. Dezember 2011, 19:44

puuh...

ich krieg das mit der globalen variable nicht hin. bisher schien mir diese variante am vielversprechensten aber im nächsten modul kann ich wieder nicht auf die variable zugreifen :cry: :

Code: Alles auswählen

    def onEingabe(self): 
        # Daten auslesen 
        d = {}
        pfad = unicode(self.pfad.text())
        if not os.path.exists(pfad):
            self.ausgabe.append("Das Verzeichnis '%s' existiert nicht." % pfad)
        alt = unicode(self.alt.text())
        #global names
        #names = glob.glob(os.path.join(pfad, "*." + alt))
        class name(object):
            def __init__(self):
                self.names = []
        s = name()
        s.names = glob.glob(os.path.join(pfad, "*." + alt))
        self.ausgabe.append("Folgende Dateien wurden gefunden:")
        self.ausgabe.append("-----------------------------------------------")
        self.ausgabe.append("\n".join(s.names))
        self.ausgabe.append("-----------------------------------------------")
BlackJack

@korkak: Mit globalen Variablen sollte man ja auch nichts hin bekommen. Klassen in Funktionen definieren ist auch ungewöhnlich. Der Name `s` ist lokal zu der Methode. Wenn die Methode abgelaufen ist, dann verschwindet der Name und damit auch das Exemplar von `name`. Das sieht nach wild herum probieren und hoffen dass es klappt aus. Schau Dir doch erst einmal Klassen und objektorientierte Programmierung ohne GUI an. Dann musst Du nicht so viele neue Konzepte auf einmal lernen.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@korkak:
Bzgl. Deiner Threading-Versuche schliesse ich mich BlackJacks Rat an - versuch nicht zu viele Konzepte auf einmal stemmen zu wollen. Das Threading ist in Deinem Bsp. völlig falsch aufgezogen, lass das besser erstmal raus und verstehe den Programmfluss in ereignisbasierter Programmierung. Mit dem nötigen Grundwissen in OOP kannst Du dies anhand eines GUI-Toolkits wie PyQt nachvollziehen. Dann wird Dir relativ schnell klar, wo und wie Du Threads zu Hilfe nehmen kannst.
korkak
User
Beiträge: 29
Registriert: Freitag 30. Dezember 2011, 19:44

naja, mir ist natürlich bewußt das ich noch viel lesen/lernen muss.
das programm an sich läuft ja jetzt eigentlich auch so wie es soll, jetzt interessiert mich einfach brennend wie man die tipps von hyperion umsetzen kann...
was ich bisher gelesen hatte ist halt, dass man mit "global" die variable mit allen modulen nutzen kann oder man schreibt die globale variablen in eine extra datei und importiert diese. ich verstehe einfach nur nicht wie ich das gleiche ergebnis mit der klasse
hinbekommen kann. :K
wenn mir da noch jemand mehr licht ins dunkel bringen könnte :)


ps: an den threads bin ich weiter dran, so leicht gebe ich nicht auf :D
korkak
User
Beiträge: 29
Registriert: Freitag 30. Dezember 2011, 19:44

so ich glaube ich habe das mit der klasse verstanden, bitte bestätigen :D

Code: Alles auswählen

import os, glob, sys
from PyQt4 import QtGui, QtCore, uic
 
class MeinDialog(QtGui.QDialog):
    
    names = []
    
    def __init__(self):
        QtGui.QDialog.__init__(self)
        self.ui = uic.loadUi("rename.ui", self)
        # Slots einrichten
        self.Eingabe.clicked.connect(self.onEingabe)
        self.Los.clicked.connect(self.onLos)
        self.Loeschen.clicked.connect(self.onLoeschen)
        self.Ende.clicked.connect(self.onEnde)
        
    def onEingabe(self): 
        # Daten auslesen 
        d = {}
        pfad = unicode(self.pfad.text())
        if not os.path.exists(pfad):
            self.ausgabe.append("Das Verzeichnis '%s' existiert nicht." % pfad)
        alt = unicode(self.alt.text())
        #global names
        MeinDialog.names = glob.glob(os.path.join(pfad, "*." + alt))
        self.ausgabe.append("Folgende Dateien wurden gefunden:")
        self.ausgabe.append("-----------------------------------------------")
        self.ausgabe.append("\n".join(MeinDialog.names))
        self.ausgabe.append("-----------------------------------------------")
 
    def onLoeschen(self):
        self.pfad.clear()
        self.alt.clear()
        self.neu.clear()
        
    def onLos(self):
        if MeinDialog.names:
            neu = unicode(self.neu.text())
            for name in MeinDialog.names:
                os.rename(name, os.path.splitext(name)[0]+'.'+neu)
            self.ausgabe.append("-----------------------------------------------")
            self.ausgabe.append("%d Dateien wurden umbenannt." % len(MeinDialog.names))            
                        
        else:
            self.ausgabe.append("Bitte zuerst ein Verzeichnis angeben!")
 
    def onEnde(self): 
        self.close()
 
app = QtGui.QApplication(sys.argv) 
dialog = MeinDialog() 
dialog.show() 
sys.exit(app.exec_())
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

korkak hat geschrieben:so ich glaube ich habe das mit der klasse verstanden, bitte bestätigen :D
Negativ!

Ich hatte es Dir doch oben schon einmal korrekt gezeigt... nach welchem Buch lernst Du denn? Woher hast Du das, was Du da jetzt gemacht hast?
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
korkak
User
Beiträge: 29
Registriert: Freitag 30. Dezember 2011, 19:44

hi hyperion,

kannst du bitte begründen warum mein vorgehen falsch ist? für mein verständsnis habe ich deinen vorschlag richtig umgesetzt. um besser nachvollziehen zu können warum ich dieser meinung bin, versuche ich die funktionsweise meiner gui zu erklären.

die gui hat 3 eingabefelder für pfad, alte endung und neue endung.
wenn man nun auf den button übernehmen(modul onEingabe) klickt wird die variable names, die jetzt nicht mehr mit global deklariert ist, sondern als attribut der klasse MeinDialog definiert ist, befüllt und eine meldung über die gefunden dateien wird in der gui ausgegeben.
wenn man nun den button umbenennen(modul onLos) klickt, greift das modul auf die variable names zu, benennt die dateien um und gibt eine meldung in der gui aus wieviele dateien umbenannt wurden.

für mich macht diese vorgehensweise sinn, falls es doch falsch sein sollte erkläre es bitte, ich möchte es doch lernen.


zu deiner frage, woher ich meine infos habe, ich lese im moment folgende seite:

http://www.python-kurs.eu/klassen.php


danke und gruß korkak
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

korkak hat geschrieben: zu deiner frage, woher ich meine infos habe, ich lese im moment folgende seite:

http://www.python-kurs.eu/klassen.php
Vergiss dieses Tutorial am besten - da steht jede Menge Mist drin! Erinnert mich auch irgend wie an das OpenBook... "Kontoklasse"... war mir doch so?

Benutze doch lieber mal das offizielle Tutorial, von mir aus auch die Übersetzung: tutorial.pocoo.org. Und schau Dir noch mal mein Beispiel an - das sind ja nur wenige Zeilen und dann vergleiche das mal mit Deiner Lösung. Du wirst definitiv einen Unterschied finden. Und diesen kannst Du auch durch das Tutorial nachvollziehen und verstehen.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Dein `name`-Attribut ist insofern nicht ganz korrekt gesetzt, weil man in den meisten Fällen ein Attribut auf Exemplar-Ebene und nicht auf der Klasse selbst nutzen möchte. Als kleine Veranschaulichung mal ein konstruiertes sinnloses Beispiel:

Code: Alles auswählen

>>> class NameManager(object):
...     names = []
...     def add_name(self, name):
...         self.names.append(name)
... 
>>> women = NameManager()
>>> women.add_name('Peggy')
>>> women.add_name('Sandra')
>>> women.names
['Peggy', 'Sandra']
>>> men = NameManager()
>>> men.add_name('Barney')
>>> men.add_name('Paul')
>>> women.names
['Peggy', 'Sandra', 'Barney', 'Paul']
Wie du siehts, führt dieser Ansatz zu vom Benutzer unerwartetem Verhalten. Abhilfe schafft Folgendes:

Code: Alles auswählen

>>> class CorrectNameManager(object):
...     def __init__(self):
...         self.names = []
...     def add_name(self, name):
...         self.names.append(name)
... 
>>> women = CorrectNameManager()
>>> women.add_name('Peggy')
>>> women.add_name('Sandra')
>>> women.names
['Peggy', 'Sandra']
>>> men = CorrectNameManager()
>>> men.add_name('Barney')
>>> men.add_name('Paul')
>>> women.names
['Peggy', 'Sandra']
>>> men.names
['Barney', 'Paul']
Mit "Exemplar" ist übrigens die Art von Entität (nenn ich jetzt mal so) gemeint, die als `women` bzw `men` genutzt wird. Also nicht das Klassenobjekt an sich, sondern eben das "Ding", worauf man irgendwelche Aktionen durchführen möchte.

Und falls das Vorgehen noch nicht so ganz klar geworden sein sollte: Klassenattribute sind quasi statisch, d.h. du kannst sie im Prinzip immer ändern. Selbst so etwas ginge:

Code: Alles auswählen

>>> class Foo(object):
...     bar = []
...     def give_bar(self):
...         return self.bar
... 
>>> foo = Foo()
>>> foo.give_bar()
[]
>>> foo2 = Foo()
>>> foo2.bar.append('spam')
>>> Foo.bar.append('eggs')
>>> foo.give_bar()
['spam', 'eggs']
An Klassenattributen kann also so ziemlich jeder nach Lust und Laune rumfummeln, auch wenn beim letzten Beispiel offenkundig schon ein gewisser Vorsatz vorliegen muss. In Python verbieten wir ja bekanntlich ungerne Dinge, sondern vertrauen eher darauf, dass der Benutzer schon keinen Mist machen wird. In der Realität kann aber zumindest das Beispiel mit den Männer- und Frauennamen durchaus vorkommen und dann für entsprechende Verwirrung (oder schlimmer) sorgen. Also sowas am Besten gar nicht erst angewöhnen, außer man braucht tatsächlich ein statisches Attribut (was aber eher selten vorkommt).
korkak
User
Beiträge: 29
Registriert: Freitag 30. Dezember 2011, 19:44

danke erst einmal für eure geduld, ihr seht schon mir fällt das thema nicht so leicht.

@hyperion, da hab ich ja wieder mal in klo gegriffen, beim versuch eine deutsche doku zu finden... ich fang nochmal von vorne an mit deinem link, danke.

@snafu, super erklärung, danke dir.
ich habe nun verstanden, dass statische variablen genauso beliebt sind wie die "global" funktion, sicherlich in einigen situationen hilfreich aber wenn es um kapselung in der OOP geht nicht geeignet.
mit women und men hast du zwei instanzen der klasse geschaffen, die unterschiedliche werte speichern können. bei mir will aber einfach nicht der groschen fallen, wie ich dies in meinem fall umsetzen kann....obwohl, ich schätze ich muss meine denkweise ändern, ich versuche die ganze zeit diesselbe variable mit 2 modulen zu nutzen, was in OOP ja nicht getan werden sollte. macht es mehr sinn, wenn ich mir die variable in den beiden modulen unabhängig voneinander zusammenbaue?


danke und gruß
korkak
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Na, du legst die Liste für deine Namen halt in der `__init__`-Methode des Widgets an und nicht auf Klassenebene.
korkak hat geschrieben:ich versuche die ganze zeit diesselbe variable mit 2 modulen zu nutzen, was in OOP ja nicht getan werden sollte.
Warum sollte das nicht getan werden? :o
korkak
User
Beiträge: 29
Registriert: Freitag 30. Dezember 2011, 19:44

ich dachte von wegen kapselung in oop, ich glaube ich seh den wald vor lauter bäumen nicht mehr...

das ganze sieht dann so aus oder sollte ich besser noch im init teil eine instanz der klasse erzeugen und darüber auf die variable zugreifen?

Code: Alles auswählen

# -*- coding: utf-8 -*-

import os, glob, sys
from PyQt4 import QtGui, QtCore, uic
class MeinDialog(QtGui.QDialog):
    
    def __init__(self):
        self.names = []
        QtGui.QDialog.__init__(self)
        self.ui = uic.loadUi("rename.ui", self)
        # Slots einrichten
        self.Eingabe.clicked.connect(self.onEingabe)
        self.Los.clicked.connect(self.onLos)
        self.Loeschen.clicked.connect(self.onLoeschen)
        self.Ende.clicked.connect(self.onEnde)
        
    def onEingabe(self): 
        # Daten auslesen und gefundene Dateien ausgeben
        d = {}
        pfad = unicode(self.pfad.text())
        if not os.path.exists(pfad):
            self.ausgabe.append("Das Verzeichnis '%s' existiert nicht." % pfad)
        alt = unicode(self.alt.text())
        MeinDialog.names = glob.glob(os.path.join(pfad, "*." + alt))
        self.ausgabe.append("Folgende Dateien wurden gefunden:")
        self.ausgabe.append("-----------------------------------------------")
        self.ausgabe.append("\n".join(MeinDialog.names))
        self.ausgabe.append("-----------------------------------------------")

    def onLoeschen(self):
        #Eingabefelder Löschen
        self.pfad.clear()
        self.alt.clear()
        self.neu.clear()
        
    def onLos(self):
        #Dateien umbenennen
        neu = unicode(self.neu.text())
        for name in MeinDialog.names:
            os.rename(name, os.path.splitext(name)[0]+'.'+neu)
        self.ausgabe.append("-----------------------------------------------")
        self.ausgabe.append("%d Dateien wurden umbenannt." % len(MeinDialog.names))

    def onEnde(self):
        #Gui schließen
        self.close()

app = QtGui.QApplication(sys.argv) 
dialog = MeinDialog() 
dialog.show() 
sys.exit(app.exec_())
BlackJack

@korkak: Du hast es immer noch nicht verstanden, denn Du verwendest immer noch ein *Klassenattribut* für die Namen.
Antworten