property auf listen

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
conloos
User
Beiträge: 22
Registriert: Freitag 23. November 2007, 09:54

Hallo,

ich hab folgendes Schnipsel:

Code: Alles auswählen

def set_to_event_queue(self, event):
        u"""Fügt das Event in die queue *event_queue* ein.
        
        Organisation: fifo"""
        
        print 'set'
        
        try:
            self.__event_queue_lock.acquire()
            self.__event_queue.append(event)
            self.__event_queue_lock.release()
        except Exception, e:
            print (_(u'Der Zugriff auf die Queue ist fehlgeschlagen: %s' % e))
            raise InitializationException

    def del_from_event_queue(self):
        u"""
        Organisation: fifo
        @return: event""" # @fixme: header
        
        print 'del'
        
        try:
            self.__event_queue_lock.acquire()
            event_queue = self.__event_queue.pop()
            self.__event_queue_lock.release()
            return event_queue
        except IndexError:
            return None
        except Exception, e:
            print (_(u'Der Zugriff auf die Queue ist fehlgeschlagen: %s' % e))
            raise InitializationException
    
    def get_event_queue(self):
        u"""Gibt die Eventqueue als Liste aus.
        
        @return: event_queue"""
        
        print 'get'
        
        try:
            self.__event_queue_lock.acquire()
            event_queue = self.__event_queue
            self.__event_queue_lock.release()
            return event_queue
        except Exception, e:
            print (_(u'Der Zugriff auf die Queue ist fehlgeschlagen: %s' % e))
            raise InitializationException
    
    event_queue = property(get_event_queue,set_to_event_queue,del_from_event_queue,'event_queue property')
Der Code basiert auf dem Artikel (http://openbook.galileocomputing.de/pyt ... 12_001.htm).

_Hintergrund_
Ich baue an einer Klasse auf die mehrere Threads zugreifen und möchte die queue schützen. Ich weiß das ich dafür auch ein Queue- Objekt nutzen kann, wollte ich hier aber nicht.

_Problem_
Es funktioniert nicht wie erwartet.

Code: Alles auswählen

$ python
Python 2.6.4 (r264:75706, Nov  2 2009, 14:38:03)
[GCC 4.4.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import plugin
>>> p = plugin.Plugin()
>>> print p
<Plugin(Thread-1, initial)>
>>> p.event_queue
get
[]
>>> p.event_queue.append('lala')
get
>>> p.event_queue
get
['lala']
>>>
Wenn ich lesend auf die queue zugreife sieht man, dass es geht.
Doch der Zugriff über append() geht nicht durch das property().

Code: Alles auswählen

>>> p.event_queue.append('lala')
get
>>> p.event_queue
get
['lala']
>>> p.event_queue = 'lala'
set
>>> p.event_queue
get
['lala', 'lala']
>>> p.event_queue = 'lele'
set
>>> p.event_queue
get
['lala', 'lala', 'lele']
Wie man sieht geht das direkte zuweisen wie erwartet, jedoch nicht andere Methoden die auf eine Liste angewendet werden könne.
Wenn jetzt jemand anderes mit der Klasse arbeitet, nehme ich an, das er sich nur anschaut von welchem type event_queue ist und unteranderem über append() zugreifen will.

_Frage_
Muss ich jetzt eine neue Klasse erzeugen die von list erbt um das abzufangen, oder kann man das property() entsprechend anpassen.

Danke

Con
lunar

Deine Erwartung ist falsch, "property" funktioniert wie von der Dokumentation garantiert. Eine Eigenschaft fängt nur den Attributzugriff für das Attribut ab, für welches die definiert wurde. Mit den vom Getter zurückgegebenen Objekten hat die Eigenschaft aber nichts zu tun.

Dein ganzer Ansatz ist auch nicht glücklich. Wenn der gesamte Zugriff auf ein Objekt (in Deinem Fall die Liste) synchron sein soll, dann muss das Objekt selbst dafür sorgen. Du aber versuchst, die Synchronisierung von außen aufzuzwingen, was auf Dauer nicht funktionieren kann.

Entweder also implementierst Du basierend auf "list" Deine eigene Queue-Klasse, oder Du verwendest - was jeder vernünftige Programmierer tun würde - die Queue-Implementierung der Standardbibliothek.

Das Openbook hat übrigens einen äußerst schlechten Ruf in diesem Forum, insbesondere das von Dir gezeigte Kapitel wird im Allgemeinen als besonders schlecht angesehen. Ein Mitglied dieses Forums hat die Kritik auf seiner Seite zusammengefasst [1].

[1] http://bj.spline.de/python_openbook.html
BlackJack

@conloos: Vorweg: Das Galileo-Buch ist insbesondere im Kapitel über OOP ziemlicher Schrott. Das ist kein idiomatisches Python was die da zeigen. Die ganzen führenden Unterstriche zum Beispiel sind in Python eher unüblich. Wenn etwas ein Implementierungsdetail ist, dann verwendet man *einen* Unterstrich.

Die Namen `set_*` und `del_*` sind IMHO ein wenig unpassend. Es wird ja nichts gesetzt, sondern hinzugefügt, und bei `del_*` wird nicht jedem klar, dass die Methode etwas zurück gibt. Da die für ein `property()` verwendet werden, solltest Du den Methoden einen Unterstrich voranstellen, sonst gibt es mehrere öffentliche Wege, das Gleiche zu erreichen.

Die ganzen ``print``-Ausgaben sehen mir eher nach Kandidaten für das `logging`-Modul aus.

Ansonsten ist mir nicht ganz klar, was Du da machen willst!? Wieso gibst Du die "Queue", also die Liste überhaupt raus, wenn Du nicht willst, dass da jemand direkt drauf zugreift?

Die API ist aber sowieso reichlich komisch. Wenn ich einem Attribut etwas zuweise, erwarte ich normalerweise nicht, dass es einer Liste hinzugefügt wird. Warum machst Du das nicht explizit?

Und das mit dem ``del`` wird auch nicht funktionieren, denn die ``del``-Anweisung ist kein Ausdruck, hat also kein Ergebnis.

Warum keine `queue`?
conloos
User
Beiträge: 22
Registriert: Freitag 23. November 2007, 09:54

also,

@alle
- erstmal danke, das ihr euch damit auseinander setzt.
- das, dass galileo Buch hier nicht gut ankommt weiß ich, aber so kann man mal schnell zeigen wie man es gemeint hat, ohne das es in einer Beschreibungsorgie endet. Zumal im "Das Python Praxishandbuch" nicht mehr und in "Dive Into Python", sowie "Einführung in Python" nichts zu property's steht.

@lunar
Ich entwickle das Projekt evolutionär, aus dem Grund habe ich erste eine Liste genommen um eine Queue aufzubauen, da ich das Programm gerade auf Threading umstelle und viele konkurrierende Zugriffe zu erwarten sind, wollte ich "nur" die Liste schützen. Dadurch wurde das immer komplizierter und mit dem property() wollte ich es wieder wie ein normale Attribut wirken lassen. Dabei hab ich im "Das Python Praxishandbuch" eine Implementierung mit Queue() gesehen, die kam mir aber (bis jetzt) zu gewaltig vor.
Edit: In dem Buch wird Queue() nicht behandelt ... hab ich irgendwo anders gelesen.


@BlackJack
- ja die Namenswahl war eher schlecht, auch das die Methoden für das property() mit einem "_*" als nicht 'von außen zu nutzen' zu kennzeichnen sind, ist vollkommen richtig und werde ich beim nächsten mal gesondert betrachten.
Ich benutze in dem gesamten Projekt logging(), das macht es mitlerweile ziemlich unübersichtlich, weswegen ich hier die prints rein geworfen habe, die heben sich halt raus :o)
Die Liste nutze ich, weil sich am einfachsten damit Fifo- Queue's aufbauen lassen. Bei Threading müssen diese halt geschützt werden, was ich hier versucht habe ...
Die del_*() ist vollkommender mist.

Bei meinem Programm wird zwischen den Threads massig kommuniziert, ich wollte eine Lösung haben die 'klein' ist. Bemerke hier aber eindeutig, das Queue() die Sache massiv vereinfacht.


Vielen dank

con
Antworten