Seite 1 von 1

dict: __setitem__ überschreiben...

Verfasst: Montag 6. Februar 2006, 18:39
von jens
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

Verfasst: Dienstag 7. Februar 2006, 08:32
von jens
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.

Verfasst: Dienstag 7. Februar 2006, 11:20
von henning
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.

Verfasst: Dienstag 7. Februar 2006, 11:23
von BlackJack
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.