Seite 1 von 2

Verfasst: Dienstag 16. November 2004, 21:40
von jens
Ahhh Halt... Ich sehe gerade, das die veränderung eines Wertes die Reihenfolge durcheinander bring :(

Code: Alles auswählen

MySortedDict["Key2"]="Wert2XX"

Verfasst: Dienstag 16. November 2004, 21:45
von Milan
Hi. Ja, das hab ich mir so gedacht. Ansonsten musst du halt __setitem__ verändern, dass der wert nicht gelöscht wird, falls vorhanden (und dann aber auch nicht noch hinzugefügt wird).

Verfasst: Dienstag 16. November 2004, 21:49
von jens
Thx.... So geht's:

Code: Alles auswählen

class SortedDict(dict):

    __slots__=["__keylist"]

    def __init__(self,*args,**kw):
        dict.__init__(self)
        self.__keylist=[]

    def __iter__(self):
        return iter(self.__keylist)

    def __setitem__(self,k,v):
        dict.__setitem__(self,k,v)
        if not k in self.__keylist:
            self.__keylist.append(k)

    def keys(self):
        return self.__keylist[:]

Code: Alles auswählen

Key1 - Wert1
Key2 - Wert2
Key3 - Wert3
===============
Key1 - Wert1
Key2 - Wert2XX
Key3 - Wert3
Key4 - Wert4
Key5 - Wert5

Verfasst: Dienstag 16. November 2004, 22:20
von Dookie
Hi jens,

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
    Modul:          Lict
    Description:    Mix of list and dict
    Version:        0.1
    Copyright:      2004 by Fritz Cizmarov fritz@sol.at
    Created:        16. Nov. 2004
    Last modified:  16. Nov. 2004
    License:        free
    Requirements:   Python2.3
    Exports:        Classes and Functions to export
"""


class Index(int):
    """ Helperclass for access Lict by Index """
    __slots__ = []

class Lict(dict):
    
    __slots__ = ["__keylist"]
    
    def __init__(self, *args, **kw):
        super(Lict, self).__init__(*args, **kw)
        self.__keylist = []
        if len(args) == 1 and isinstance(args[0], (tuple, list)):
            for key, value in args[0]:
                self.__keylist.append(key)
        for key in kw:
            self.__keylist.append(key)
    
    def __getitem__(self, key):
        if type(key) is Index:
            key = self.__keylist[key]
        return super(Lict, self).__getitem__(key)

    def __setitem__(self, key, value):
        """ sets item, if item not exists append it """
        if type(key) is Index:
            key = self.__keylist[key]
        elif key not in self.__keylist:
            self.__keylist.append(key)
        super(Lict, self).__setitem__(key, value)

    def __delitem__(self, key): 
        if type(key) is Index: 
            key = self.__keylist[key] 
        super(Lict, self).__delitem__(key) 
        del self.__keylist[key]

    def __str__(self): 
        tpl = "{"+("%s : %s, "*len(self.__keylist))[:-2]+"}" 
        if self.__keylist: 
            data = [repr(x) for x in reduce(lambda a, b: a+b, self.iteritems())] 
            return tpl % tuple(data) 
        else: 
            return tpl 

    def __repr__(self): 
        tpl = "Lict(["+("(%s, %s), "*len(self.__keylist))[:-2]+"])" 
        if self.__keylist: 
            data = [repr(x) for x in reduce(lambda a, b: a+b, self.iteritems())] 
            return tpl % tuple(data) 
        else: 
            return tpl
    def __iter__(self):
        return iter(self.__keylist)

    def iteritems(self):
        for key in self.__keylist:
            yield key, self[key]

    iterkeys = __iter__

    def itervalues(self):
        for key in self.__keylist:
            yield self[key]
            
    def update(self, E):
        if not isinstance(E, Lict):
            raise TypeError("E is not from type Lict!")
        for key in E:
            self[key] = E[key]
    
    def pop(self, key=None):
        if key is None:
            key = self.__keylist[-1]
        elif type(key) is Index:
            key = self.__keylist[key]
        self.keylist.remove(key)
        return super(Lict, self).pop(key)

    def reverse(self):
        self.__keylist.reverse()

    def sort(self):
        self.__keylist.sort()

    def insert(self, index, key, value): 
        self.__keylist.insert(index, key) 
        super(Lict, self).__setitem__(key, value)

if __name__ == "__main__":
    a = Lict((('a', "eins"),('b', "zwei"), ('c', "drei")))
    print a
    a[Index(1)]="neu"
    print a
    a["d"] = "ganzneu"
    print a
    for i in xrange(len(a)):
        print a[Index(i)],
    for i in a:
        print i,
Hab auch mal was gebastelt. Index ist eine Hilfsklasse um auch über den Index auf die Einträge im Dictionary zugreifen zu können.


Gruß

Dookie

Edit by Milan: Änderungen von Dookie zwecks Übersichtlichkeit eingefügt

Verfasst: Mittwoch 17. November 2004, 13:48
von Milan
Hi. Nett, aber nicht ganz in Ordnung:

Code: Alles auswählen

>>> Lict()

Traceback (most recent call last):
  File "<pyshell#9>", line 1, in -toplevel-
    Lict()
  File "<pyshell#1>", line 40, in __repr__
    data = [repr(x) for x in reduce(lambda a, b: a+b, self.iteritems())]
TypeError: reduce() of empty sequence with no initial value
>>> Lict({"a":"b"})

Traceback (most recent call last):
  File "<pyshell#10>", line 1, in -toplevel-
    Lict({"a":"b"})
  File "<pyshell#1>", line 40, in __repr__
    data = [repr(x) for x in reduce(lambda a, b: a+b, self.iteritems())]
TypeError: reduce() of empty sequence with no initial value
Kann man außerdem nicht das superobj als attribut speichern? Sonst muss es ja jedesmal erzeugt werden...

Verfasst: Mittwoch 17. November 2004, 14:03
von Dookie
Hi,

uups stimmt, hab halt nich alles getestet, is aber nur ne Abfrage nötig beim __repr__ und __str__:

Code: Alles auswählen

    def __str__(self):
        tpl = "{"+("%s : %s, "*len(self.__keylist))[:-2]+"}"
        if self.__keylist:
            data = [repr(x) for x in reduce(lambda a, b: a+b, self.iteritems())]
            return tpl % tuple(data)
        else:
            return tpl

    def __repr__(self):
        tpl = "Lict(["+("(%s, %s), "*len(self.__keylist))[:-2]+"])"
        if self.__keylist:
            data = [repr(x) for x in reduce(lambda a, b: a+b, self.iteritems())]
            return tpl % tuple(data)
        else:
            return tpl
nö super könnte man schlecht in einem Attribut speichern, dann könnte man von Lict keine Klassen mehr ableiten da ja super dann für diese abgeleiteten Klassen nicht mehr stimmen würde! Besser die Metaklasse für autosuper aus dem Beispiel auf der Pythonhomepagedokumentation zu Newstyleklassen verwenden.


Gruß

Dookie

Verfasst: Freitag 19. November 2004, 23:48
von jens
Mit __delitem__ scheint auch was nicht zu stimmen:

Code: Alles auswählen

  File "SortedDict.py", line 132, in ?
    del( MySortedDict["Key2"] )
  File "SortedDict.py", line 49, in __delitem__
    super(Lict, self).__delitem(key)
AttributeError: 'super' object has no attribute '_Lict__delitem'
Wie geht es außerdem einen Wert an einer bestimmten Stelle hinzuzufügen?

Code: Alles auswählen

    MyLict["Key1"]="Wert1"
    MyLict["Key2"]="Wert2"
    MyLict["Key3"]="Wert3"
Also Beispielsweise zwischen Key2 und Key3, soll MyLict["Key2b"]="Wert2b" rein...

Vielleicht ist es für mich persönlich doch einfach zwei Listen zu verwalten...

Verfasst: Samstag 20. November 2004, 12:56
von Dookie
Hi,

Da fehlen 2 "_" :)

Code: Alles auswählen

    def __delitem__(self, key):
        if type(key) is Index:
            key = self.__keylist[key]
        super(Lict, self).__delitem__(key)
        del self.__keylist[key]
Das Einfügen an einem Bestimmten Index ginge so:

Code: Alles auswählen

    def insert(self, index, key, value):
        self.__keylist.insert(index, key)
        super(Lict, self)[key] = value
Gruß

Dookie

Verfasst: Samstag 20. November 2004, 19:52
von jens
Dookie hat geschrieben:Da fehlen 2 "_" :)
das ist es nicht ganz:

Code: Alles auswählen

    def __delitem__(self, key):
        if type(key) is Index:
            key = self.__keylist[key]
        super(Lict, self).__delitem__(key)
        del self.__keylist[ self.__keylist.index(key) ]
(Die letzte Zeile ist anders)

Code: Alles auswählen

    MyLict.insert(2, "Key2", "Wert2")
Geht leider nicht:

Code: Alles auswählen

Traceback (most recent call last):
  File "SortedDict.py", line 138, in ?
    MyLict.insert(2, "Key2", "Wert2")
  File "SortedDict.py", line 54, in insert
    super(Lict, self)[key] = value
TypeError: object does not support item assignment

Verfasst: Samstag 20. November 2004, 20:16
von Dookie

Code: Alles auswählen

    def insert(self, index, key, value):
        self.__keylist.insert(index, key)
        super(Lict, self).__setitem__(key, value)
so getestet und läuft :)


Dookie

Verfasst: Samstag 20. November 2004, 21:33
von jens
Jup! Jetzt geht's...

Damit man nicht den ganzen Thread durchlesen muß, hier nochmal die aktuelle Version, mit allen Verbesserungen:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
    Modul:          Lict
    Description:    Mix of list and dict
    Version:        0.1.1
    Copyright:      2004 by Fritz Cizmarov fritz@sol.at
    Created:        16. Nov. 2004
    Last modified:  20. Nov. 2004
    License:        free
    Requirements:   Python2.3
    Exports:        Classes and Functions to export
"""


class Index(int):
    """ Helperclass for access Lict by Index """
    __slots__ = []

class Lict(dict):

    __slots__ = ["__keylist"]

    def __init__(self, *args, **kw):
        super(Lict, self).__init__(*args, **kw)
        self.__keylist = []
        if len(args) == 1 and isinstance(args[0], (tuple, list)):
            for key, value in args[0]:
                self.__keylist.append(key)
        for key in kw:
            self.__keylist.append(key)

    def __getitem__(self, key):
        if type(key) is Index:
            key = self.__keylist[key]
        return super(Lict, self).__getitem__(key)

    def __setitem__(self, key, value):
        """ sets item, if item not exists append it """
        if type(key) is Index:
            key = self.__keylist[key]
        elif key not in self.__keylist:
            self.__keylist.append(key)
        super(Lict, self).__setitem__(key, value)

    def __delitem__(self, key):
        if type(key) is Index:
            key = self.__keylist[key]
        super(Lict, self).__delitem__(key)
        del self.__keylist[ self.__keylist.index(key) ]

    def insert(self, index, key, value):
        self.__keylist.insert(index, key)
        super(Lict, self).__setitem__(key, value)

    def __str__(self):
        tpl = "{"+("%s : %s, "*len(self.__keylist))[:-2]+"}"
        if self.__keylist:
            data = [repr(x) for x in reduce(lambda a, b: a+b, self.iteritems())]
            return tpl % tuple(data)
        else:
            return tpl

    def __repr__(self):
        tpl = "Lict(["+("(%s, %s), "*len(self.__keylist))[:-2]+"])"
        if self.__keylist:
            data = [repr(x) for x in reduce(lambda a, b: a+b, self.iteritems())]
            return tpl % tuple(data)
        else:
            return tpl

    def __iter__(self):
        return iter(self.__keylist)

    def iteritems(self):
        for key in self.__keylist:
            yield key, self[key]

    iterkeys = __iter__

    def itervalues(self):
        for key in self.__keylist:
            yield self[key]

    def update(self, E):
        if not isinstance(E, Lict):
            raise TypeError("E is not from type Lict!")
        for key in E:
            self[key] = E[key]

    def pop(self, key=None):
        if key is None:
            key = self.__keylist[-1]
        elif type(key) is Index:
            key = self.__keylist[key]
        self.keylist.remove(key)
        return super(Lict, self).pop(key)

    def reverse(self):
        self.__keylist.reverse()

    def sort(self):
        self.__keylist.sort()






if __name__=="__main__":
    print "->",__file__,"<- SelbstTest\n"

    def LictAusgeben():
        print "="*40
        for k,v in MyLict.iteritems():
            print k,"-",v
        print "="*40

    MyLict = Lict()

    MyLict["Key1"]="Wert1"
    MyLict["Key2"]="Wert2"
    MyLict["Key3"]="Wert3"

    LictAusgeben()

    MyLict["Key2"]="Wert2XX"

    MyLict["Key4"]="Wert4"
    MyLict["Key5"]="Wert5"

    LictAusgeben()

    del( MyLict["Key2"] )

    LictAusgeben()

    MyLict.insert(2, "Key2", "Wert2NEU")

    LictAusgeben()