Seite 1 von 2

Dictionary- Konstruktor

Verfasst: Samstag 2. Dezember 2006, 16:51
von rolgal_reloaded
Hallo,

wie sieht denn der Konstruktor der Klasse dict aus?
Denn man kann ja leere Dictionaries oder nicht leere Dictionaries erstellen.

LG

rolgal_reloaded

Verfasst: Samstag 2. Dezember 2006, 17:06
von birkenfeld
1. dict() -> leer
2. dict(x) -> dict von x, was entweder ein Mapping oder eine Sequenz von 2-Sequenzen sein muss
3. dict(a=1, b=2) -> {'a': 1, 'b': 2}

Verfasst: Samstag 2. Dezember 2006, 17:18
von rolgal_reloaded
Ich bin wohl undeutlich, also alles von vorn:

Ich habe hier eine kleine Spielerei begonnen. Wir wissen ja folgendes:

Code: Alles auswählen

d.keys()
d.values()
d.items()
Damit bekommen wir verschiedene Listen aus einem Dictionary zurück, die sind aber nie sortiert. Oft will man aber sortierte Listen, weshalb es dann Gott sei Dank die Methode sort() für Listen gibt.

Aus Jux und vielleicht als Möglichkeit für ein Lehrbeispiel von OOP habe ich versucht eine Klasse zu machen, dass beim Aufruf der genannten Methoden diese bereits eine sortierte Liste zurückgeben.

Eigentlich funktioniert auch alles, ich habe mir nur zu Beginn zu wenig Gedanken um den Konstruktor gemacht:

Code: Alles auswählen

class MyDict(dict):

    def __init__(self):
        dict.__init__(self)

    def items(self):
        return sorted([(key,self[key]) for key in self])
    
    def values(self):
        return sorted([self[key] for key in self])

    def keys(self):
        return sorted([key for key in self])   



if __name__=="__main__":
    
    laender_staedte = MyDict()    
    laender_staedte["Italien"] = "Rom"
    laender_staedte["Spanien"] = "Madrid"
    laender_staedte["Belgien"] = "Brüssel"
    laender_staedte["Frankreich"] = "Paris"

Code: Alles auswählen

>>> laender_staedte
{'Spanien': 'Madrid', 'Italien': 'Rom', 'Frankreich': 'Paris', 'Belgien': 'Br\xfcssel'}
>>> laender_staedte.items()
[('Belgien', 'Br\xfcssel'), ('Frankreich', 'Paris'), ('Italien', 'Rom'), ('Spanien', 'Madrid')]
>>> laender_staedte.values()
['Br\xfcssel', 'Madrid', 'Paris', 'Rom']
>>> laender_staedte.keys()
['Belgien', 'Frankreich', 'Italien', 'Spanien']
>>> 
Jetzt würde ich natürlich gern mein Dictionary nicht immer so erstellen müssen.
Klasse wäre, wenn ich ein leeres oder auch eines mit Schlüsseln und Werten erstellen könnte.

LG

rolgal_reloaded

Verfasst: Samstag 2. Dezember 2006, 17:23
von sape
probiere mal so:

Code: Alles auswählen

laender_staedte = MyDict({
    'key1': 'value1',
    'key2': 'value2',
    # etc
})  
Ich hoffe ich hab deine Frage richtig verstanden.

lg

Verfasst: Samstag 2. Dezember 2006, 17:29
von rolgal_reloaded
Hallo XtraNine,

klar hast du mich richtig verstanden, aber so kann es nicht gehen, weil mein Konstruktor keine Argumente übernimmt.

Da gibts nur self - würde auch gern dabei bleiben, ich bilde mir ein, dass das sinnig ist.

LG

rolgal_reloaded

Verfasst: Samstag 2. Dezember 2006, 17:31
von birkenfeld
Wozu überschreibst du überhaupt den Konstruktor? Lass __init__ einfach weg.

Verfasst: Samstag 2. Dezember 2006, 17:36
von rolgal_reloaded
Hallo birkenfeld,

das geht! Aber: ich überschreibe ihn zwar rufe ihn aber ja explicit auf.
Aus didaktischen Gründen, quasi zur Demonstration der Vorgehensweise bei einer Vererbung hätte ich ihn gern drin gehabt.

Warum kommt da eigentlich nicht das gleiche raus, das verwirrt mich jetzt :?:
-na weil der Konstruktor von dict wohl etwas komplexer aussieht - Versuch einer Selbstantwort, ggg

LG

rolgal_reloaded

Verfasst: Samstag 2. Dezember 2006, 17:49
von BlackJack
So übergibst Du einfach alles an den Konstruktor von `dict()` was Dein Konstruktor so bekommt:

Code: Alles auswählen

class MyDict(dict):
    def __init__(self, *args, **kwargs):
        dict.__init__(self, *args, **kwargs)
    
    def items(self):
        return sorted(self.iteritems())
    
    def values(self):
        return sorted(self.itervalues())
    
    def keys(self):
        return sorted(self.iterkeys())
Ausserdem hab' ich die unnötigen List-Comps rausgeworfen.

Das mit den Schlüsselwort-Argumenten war übrigens eine blöde Idee von den Python-Machern -- man kann `dict()` nicht beerben und der neuen Klasse Schlüsselwortargumente hinzufügen ohne das sich die Semantik ändert. Bei dem sortierten Dict wäre es ja zum Beispiel schön im Konstruktor eine Schlüsselfunktion zum sortieren anzugeben.

Verfasst: Samstag 2. Dezember 2006, 17:51
von birkenfeld
Wegen der Argumente. Dein Konstruktor nimmt keine an, dict() schon.
->

Code: Alles auswählen

def __init__(self, *args, **kwds):
    dict.__init__(self, *args, **kwds)

Verfasst: Samstag 2. Dezember 2006, 18:04
von rolgal_reloaded
@BlackJack,

danke, die Listcomprehensions sind trotzdem sinnvoll. Die Schülerinnen sollen sehen, was eigentlich vor sich geht.
Was und wie diese Methoden zu den Ergebnissen kommen.

In einer früheren Fassung würde ich aus Verständnisgründen sogar den Umweg ohne Listcomprehensions machen: also Liste anlegen, dann über Liste.append() usw.

Deine Version wäre dann die Verfeinerung der 3. Stufe

LG

rolgal_reloaded

Verfasst: Samstag 2. Dezember 2006, 18:09
von birkenfeld
BlackJack hat geschrieben: Das mit den Schlüsselwort-Argumenten war übrigens eine blöde Idee von den Python-Machern -- man kann `dict()` nicht beerben und der neuen Klasse Schlüsselwortargumente hinzufügen ohne das sich die Semantik ändert. Bei dem sortierten Dict wäre es ja zum Beispiel schön im Konstruktor eine Schlüsselfunktion zum sortieren anzugeben.
Ich glaube, da greift "Practicality beats purity".

Verfasst: Samstag 2. Dezember 2006, 18:27
von BlackJack
Ist natürlich Geschmacksfrage, aber besonders praktisch fand ich die Schlüsselwortargumente bei `dict()` nicht. Jedenfalls nicht unpraktischer als ein Dictionary mit {...} stattdessen zu schreiben. Man gewinnt nicht wirklich etwas, verliert aber eine Menge Möglichkeiten.

Verfasst: Samstag 2. Dezember 2006, 18:32
von rolgal_reloaded
BlackJack hat geschrieben:Ist natürlich Geschmacksfrage, aber besonders praktisch fand ich die Schlüsselwortargumente bei `dict()` nicht. Jedenfalls nicht unpraktischer als ein Dictionary mit {...} stattdessen zu schreiben. Man gewinnt nicht wirklich etwas, verliert aber eine Menge Möglichkeiten.
Bitte um was gehts jetzt genau? Ich steh am Schlauch...

Verfasst: Samstag 2. Dezember 2006, 18:34
von birkenfeld
Eine Menge Möglichkeiten? Statt

Code: Alles auswählen

x = sorteddict(sortfunc=f)
kannst du doch

Code: Alles auswählen

x = sorteddict(None, f)
oder auch

Code: Alles auswählen

x = sorteddict()
x.setsortfunc(f)
implementieren.

Andererseits finde ich für String-Keys die dict()-Form wesentlich angenehmer, auch zu tippen.

Verfasst: Samstag 2. Dezember 2006, 18:34
von Leonidas
rolgal_reloaded hat geschrieben:Bitte um was gehts jetzt genau? Ich steh am Schlauch...
Es geht gerade um eine Design-Entscheidung von den Python-Entwicklern, die sich entschieden haben, die Funktion dict() so zu implementieren, dass sie quasi-beliebige Schlüsselwort-Argumente annimmt und daraus ein Dict konstrugiert mit den Argumenten als Key und deren Werten als Values.

Verfasst: Samstag 2. Dezember 2006, 18:44
von rolgal_reloaded
@Leonidas,

ah ja, ich bin wieder mit dabei, wobei mich die Designfrage weniger quält, also die, die ich wohl gleich stellen werde :D

LG

rolgal_reloaded

Verfasst: Samstag 2. Dezember 2006, 19:15
von rolgal_reloaded
...hm, ich glaube die Variante von birkenfeld ohne Konstruktor, da ich ihn sowieso nicht brauche ist für den Unterricht besser.

Die Geschichte mit *args und **kwargs könnte einiges an Verwirrung sorgen.

rolgal_reloaded

Verfasst: Samstag 2. Dezember 2006, 20:18
von rolgal_reloaded
BlackJack hat geschrieben:So übergibst Du einfach alles an den Konstruktor von `dict()` was Dein Konstruktor so bekommt:

Code: Alles auswählen

class MyDict(dict):
    def __init__(self, *args, **kwargs):
        dict.__init__(self, *args, **kwargs)
    
    def items(self):
        return sorted(self.iteritems())
    
    def values(self):
        return sorted(self.itervalues())
    
    def keys(self):
        return sorted(self.iterkeys())
Ausserdem hab' ich die unnötigen List-Comps rausgeworfen.

Das mit den Schlüsselwort-Argumenten war übrigens eine blöde Idee von den Python-Machern -- man kann `dict()` nicht beerben und der neuen Klasse Schlüsselwortargumente hinzufügen ohne das sich die Semantik ändert. Bei dem sortierten Dict wäre es ja zum Beispiel schön im Konstruktor eine Schlüsselfunktion zum sortieren anzugeben.
Wie schon gesagt, ist das natürlich eine schöne Sache mit iterkeys() usw.

Wenn man damit im Interpreter rumspielt bekommt man aber folgendes:

Code: Alles auswählen

>>> d = {"Italien":"Rom","Spanien":"Madrid","Belgien":"Brüssel","Frankreich":"Paris"}
>>> d.items()
[('Spanien', 'Madrid'), ('Italien', 'Rom'), ('Frankreich', 'Paris'), ('Belgien', 'Br\xfcssel')]
>>> d.keys()
['Spanien', 'Italien', 'Frankreich', 'Belgien']
>>> d.iterkeys()
<dictionary-keyiterator object at 0x01553D60>
Ich meine: wenn ich mit iterkeys() in deinem Code der Klasse MyDict dasselbe bekomme wie mit meiner Listcomprehension

Code: Alles auswählen

    def keys(self):
        return sorted([key for key in self]) 
, dann müsste ich doch in der oben gezeigten interaktiven Sitzung auch mehr rausbekommen als einen schönen Gruß übern Interpreter :D

Das check ich grad nicht ganz.

LG

rolgal_reloaded

Verfasst: Samstag 2. Dezember 2006, 20:24
von birkenfeld
Meinst du "<dictionary-keyiterator object at 0x01553D60>"?

Das ist ein sogenannter Iterator, also ein Objekt, welches nacheinander die Keys eines dict bereitstellt, wenn man auf ihm next() aufruft.

Was sollte iterkeys() sonst zurückgeben? Es soll ja gerade keine Liste sein.

Verfasst: Samstag 2. Dezember 2006, 20:34
von rolgal_reloaded
@birkenfeld

Eigentlich schon klar, aber in BlackJacks Beispiel bekomme ich dasselbe heraus, wie in meinem Beispiel mit einer Listcomprehension. Also eben sehr wohl Listen!

Deshalb bin ich verwirrt.