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.
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.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Und ich frage mich auch, wo `ausgabe` plötzlich herkommt. Nach einem Widget des `ui`-Erzeugers sieht mir das nämlich nicht aus (wegen `.append()`).

Weiterhin verweise ich an die betreffende Stelle im bereits zuvor genannten deutschen Python-Tutorial (http://tutorial.pocoo.org/classes.html). Es bringt einfach nichts, das jemandem zu erklären, der quasi noch bei Null steht im Hinblick auf das Thema "Klassen" und mehr oder weniger bloß wild rumprobiert, um irgendwie ans Ziel zu kommen.
Antworten