dict: __setitem__ überschreiben...

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
Benutzeravatar
jens
Moderator
Beiträge: 8481
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Montag 6. Februar 2006, 18:39

Ich wollte noch bei [wiki]Colubrid/Hello World[/wiki] anknüpfen und eine weitere Seite über Debugging mit Clubrid reinsetzten, doch mein Beispiel funktioniert gerade nicht so wirklich.
Ich bekomme ein Traceback mit: TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'

Das liegt irgendwie an meiner __setitem__ Aber ich check das gerade nicht, was daran falsch ist:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from colubrid import BaseApplication

class preferences(dict):
    def __init__(self, request):
        dict.__init__(self)
        self.request = request

    def __setitem__(self, item, value):
        self.request.write('<p>setitem: item %s - value %s</p>' % (item, value))
        self[item] = value


class DebugBeispiel(BaseApplication):
    def process_request(self):
        self.request.headers['Content-Type'] = 'text/html'
        self.request.write('<h1>Debug Demo:</h1>')

        self.request.preferences = preferences(self.request)
        # An Debug-Info dranpacken
        self.request.exposed.append("preferences")

        # Daten einfügen
        self.request.preferences["test1"] = "1"
        self.request.preferences["test2"] = "2"

        # Debug-Seite aufbauen
        self.request.debug_info()

app = DebugBeispiel

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Moderator
Beiträge: 8481
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Dienstag 7. Februar 2006, 08:32

OK, ich hab den "Fehler" gefunden:

Code: Alles auswählen

import sys

class preferences(dict):
    def __init__(self, request):
        dict.__init__(self)
        self.request = request

    def __setitem__(self, item, value):
        self.request.write('<p>setitem: item %s - value %s</p>\n' % (item, value))
        #~ self[item] = value
        dict.__setitem__(self, item, value)

    def test(self, key):
        print "test:"
        print self
        print self[key]

    #~ def __getitem__(self, key):
        #~ print "getitem %s" % key
        #~ print self[key]
        #~ return self[key]

p = preferences(sys.stdout)
p["jup"] = 1

print p.test("jup")

print p
Irgendwie schnall ich das aber nicht.
Hier http://www.python-forum.de/viewtopic.php?p=29301#29301 hab ich doch gesehen, das es einfacher geht, weil man direkt mit self arbeiten kann... Das scheint aber bei __setitem__() und __getitem__() nicht zu gehen. Wenn ich dort mit self[item] auf das dict zugreife, dann kommt es zu einer Endlosschleife. Anscheinend, wird damit die Methode selber wieder aufgerufen. Mit einem dict.__setitem__() geht es allerdings...

Sollte ich mir mal merken ;) Am besten ich bastel mal eine Wiki Seite dafür...

EDIT: So, ich hab mal die Seite [wiki]Colubrid/Debug expose[/wiki]angelegt. Dort könnt ihr auch mal sehen, wie deine Debug-Seite aussieht.

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
henning
User
Beiträge: 274
Registriert: Dienstag 26. Juli 2005, 18:37

Dienstag 7. Februar 2006, 11:20

Ist doch aber auch ganz logisch.
__setitem__ bzw. __getitem__ sind die Methoden, die aufgerufen werden, wenn das Objekt nen Subskript hat.
(Also wenn du a["foo"] schreibst z.B.)

self repräsentiert aber gerade genau eine Instanz deiner Klasse die du von dict abgeleitet hast.
Und in dieser Klasse hast du ja __setitem__ und __getitem__ überschrieben und musst folglich extra bekanntgeben, wenn du die "Versionen" von z.B. dict haben willst und nicht deine eigenen.
BlackJack

Dienstag 7. Februar 2006, 11:23

jens hat geschrieben: Irgendwie schnall ich das aber nicht.
Hier http://www.python-forum.de/viewtopic.php?p=29301#29301 hab ich doch gesehen, das es einfacher geht, weil man direkt mit self arbeiten kann... Das scheint aber bei __setitem__() und __getitem__() nicht zu gehen. Wenn ich dort mit self[item] auf das dict zugreife, dann kommt es zu einer Endlosschleife. Anscheinend, wird damit die Methode selber wieder aufgerufen. Mit einem dict.__setitem__() geht es allerdings...
Mit ``self[key] = value`` wird ``self.__setitem__()`` aufgerufen was natürlich zu einem rekursiven Aufruf führt, wenn man das innerhalb von ``self.__setitem__()`` macht. Wenn man ``__setitem__()`` nicht überschreibt, dann wird ja das von der Oberklasse aufgerufen.
Antworten