Klasse mehrfache ausführung

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
MarcelF6
User
Beiträge: 226
Registriert: Samstag 3. März 2012, 21:30

Hallo miteinander,
ich habe zurzeit folgende Klasse (etwas vereinfacht), die in einem grossen Text-File nach Vorkommen von "CARD" sucht, das von "Test" oder "Tests" + einem PRF gefolgt wird. Das Wort "Test" oder "Tests" soll dann in "test" verändert werden. Der Code und die Klasse funktionieren:

Code: Alles auswählen

class Test(object):    
    def __init__(self):
        self.NEs = Event(lambda w: getattr(w, "text", None), [u"Test", u"Tests"], maxdist=1, finevent=True)
        self.PRF = Event(lambda w: getattr(w, "pos", None), [u"PRF"], maxdist=2, finevent=True)
        self.CARD = Event(lambda w: w.get('pos', None), [u"CARD"], next_ev=[self.NEs], active_begin=True)
        self.pat = PoSPattern([self.CARD, self.NEs, self.PRF], self.NEPRF, "de")
        
    def NEPRF(self, resdct):
	dct[self.NEs].attrib['number'] = "2"
	dct[self.NEs].attrib['pos'] = "VV"
	dct[self.NEs].text = "test"
        
    def pattern(self):
        return self.pat  
Wenn ich nun aber einen zweiten Fall hinzufüge, also schlussendlich sowas habe:

Code: Alles auswählen

class Test(object):    
    def __init__(self):
        self.NEs = Event(lambda w: getattr(w, "text", None), [u"Test", u"Tests"], maxdist=1, finevent=True)
        self.PRF = Event(lambda w: getattr(w, "pos", None), [u"PRF"], maxdist=2, finevent=True)
        self.CARD = Event(lambda w: w.get('pos', None), [u"CARD"], next_ev=[self.NEs], active_begin=True)
        self.pat = PoSPattern([self.CARD, self.NEs, self.PRF], self.NEPRF, "de")

        self.NN = Event(lambda w: w.get('pos', None), [u"NN"], next_ev=[self.NEs], active_begin=True)
        self.pat = PoSPattern([self.NN, self.NEs, self.PRF], self.NEPRF, "de")
        
    def NEPRF(self, resdct):
	dct[self.NEs].attrib['number'] = "2"
	dct[self.NEs].attrib['pos'] = "VV"
	dct[self.NEs].text = "test"
        
    def pattern(self):
        return self.pat  
Dann wird nur der letzte Befehl ausgeführt, d.h. auch wenn es Vorkommen von " CARD + Test + PRF" hat, es werden nur die Vorkommen " NN + Test + PRF" verändert.
Wie kann ich den Code ändern, dass beide Fälle berücksichtigt werden und dass beide Fälle ausgeführt werden?

Vielen Dank,
Marcel
Sirius3
User
Beiträge: 18335
Registriert: Sonntag 21. Oktober 2012, 17:20

@MarcelF6: die erste Zuweisung an 'self.pat' wird ja auch wieder überschrieben. In der Methode NEPRF kommt "dct" aus dem Nichts. Du mußt Deine Klassen so erweitern, dass sie mit mehreren Patterns umgehen können. Das wird nicht auf magische Weise passieren.
MarcelF6
User
Beiträge: 226
Registriert: Samstag 3. März 2012, 21:30

Hm ok ja, das sehe ich.
Nur: Wie macht man das am besten / einfachsten? :S
MarcelF6
User
Beiträge: 226
Registriert: Samstag 3. März 2012, 21:30

...weil für jeden Einzelfall eine neue Klasse bilden, bringt es irgendwie nicht, oder?
Benutzeravatar
pillmuncher
User
Beiträge: 1532
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Wie wär's mit einer Liste?

Code: Alles auswählen

    def __init__(self):
        self.pats = []
        ...
        self.pats.append(PoSPattern([self.CARD, self.NEs, self.PRF], self.NEPRF, "de"))
        ...
        self.pats.append(PoSPattern([self.NN, self.NEs, self.PRF], self.NEPRF, "de"))
In specifications, Murphy's Law supersedes Ohm's.
MarcelF6
User
Beiträge: 226
Registriert: Samstag 3. März 2012, 21:30

Das habe ich so gemacht, und mit der Funktion:

Code: Alles auswählen

    def pattern(self):
	for el in range(len(self.pat)):
	    return self.pat[el] 
Allerdings wird auch so nur das letzte Auftreten berücksichtigt. :(
Sirius3
User
Beiträge: 18335
Registriert: Sonntag 21. Oktober 2012, 17:20

@MarcelF6: lies nochmal durch, was Du da geschrieben hast!
In der Zwischenzeit sei Dir gesagt, dass das Iterieren über einen Index in eine Liste total umständlich ist. So wäre es richtig:

Code: Alles auswählen

for pattern in self.pat:
    return pattern
Und jetzt sieht man auch gleich, wie weit Deine for-Schleife kommt. Nämlich nicht über das erste Element hinaus, denn dann wird die Funktion mit »return« beendet. Das ganze hättest Du also auch so schreiben können:

Code: Alles auswählen

def pattern(self):
    return self.pat[0]
MarcelF6
User
Beiträge: 226
Registriert: Samstag 3. März 2012, 21:30

Vielen Dank für den Hinweis.
Ich verstehe, dass jeweils nur das erste Element berücksichtigt wird.

Allerdings verstehe ich noch nicht, wie man alle Elemente retournieren kann, ohne dass ein "list object has no attribute 'evaluate'"-Fehler auftaucht.
Wie macht man das? :S

Besten Dank für die Hilfe! :)
Sirius3
User
Beiträge: 18335
Registriert: Sonntag 21. Oktober 2012, 17:20

@MarcelF6: wie schon weiter oben geschrieben, hilft es meistens wenig, zu hoffen, dass ein anderes Modul auf magische Weise plötzlich mit Listen umgehen kann, wo es vorher andere Objekte erwartet hat. Also, entweder gibt es eine andere Funktion, die das macht, was Du willst, oder Du mußt sie halt selbst programmieren.
Benutzeravatar
pillmuncher
User
Beiträge: 1532
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

MarcelF6 hat geschrieben:"list object has no attribute 'evaluate'"
Wo kommt denn das jetzt her? Wie soll man dir helfen, wenn du plötzlich Sachen anschleppst, die mit nichts in deinen vorhergehenden Postings in irgendeinem nachvollziehbaren Zusamenhang stehen. Wir (ich zumindest) können nicht hellsehen.

Das einzige, was ich dir empfehlen kann, ist: versuch nicht auf einer Liste die Methode evaluate() aufzurufen. Die gibt es dort nämlich nicht.
In specifications, Murphy's Law supersedes Ohm's.
MarcelF6
User
Beiträge: 226
Registriert: Samstag 3. März 2012, 21:30

Hm ok. Genau das mache ich: Ich rufe evaluate() auf eine Liste auf. :(
"simple" Alternativen dazu gibt es nicht, oder?

Andernfalls mache ich verschiedene Klassen. :)
Sirius3
User
Beiträge: 18335
Registriert: Sonntag 21. Oktober 2012, 17:20

@MarcelF6: Da niemand weiß, was Du sonst noch für Klassen benutzt, kann Dir dabei auch niemand helfen.
MarcelF6
User
Beiträge: 226
Registriert: Samstag 3. März 2012, 21:30

Mittlerweile hab ich's fast hinbekommen. :)
Ich hätte nur noch eine Frage: Wie kann man prüfen, ob es sich um ein "'function' object" handelt? Diese darf / kann / will ich nämlich ignorieren, sonst funktionieren gewisse Funktionen in meiner Klasse nicht mehr.
Sirius3
User
Beiträge: 18335
Registriert: Sonntag 21. Oktober 2012, 17:20

das hört sich für mich, dass Du wieder eine zu magische Lösung gefunden hast :wink:
Schau dir mal collections.Callable an.
BlackJack

@MarcelF6: Wenn man anfängt Objekte aufgrund ihres Typs anders zu behandeln, hat man in der Regel einen Entwurfsproblem. Das ist kein gutes OOP und in Python unterläuft man damit zusätzlich noch das „duck typing”.
MarcelF6
User
Beiträge: 226
Registriert: Samstag 3. März 2012, 21:30

Das Problem war ein Fehler meinerseits. Ich hatte nur eine Funktionsklammer vergessen. -.-
Sorry wegen der Aufregung, und danke für die Kommentare / Unterstützung. :)
Antworten