Dictionary- Konstruktor

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.
rolgal_reloaded
User
Beiträge: 312
Registriert: Dienstag 24. Oktober 2006, 19:31

Hallo,

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

LG

rolgal_reloaded
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

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}
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
rolgal_reloaded
User
Beiträge: 312
Registriert: Dienstag 24. Oktober 2006, 19:31

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
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

probiere mal so:

Code: Alles auswählen

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

lg
rolgal_reloaded
User
Beiträge: 312
Registriert: Dienstag 24. Oktober 2006, 19:31

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
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

Wozu überschreibst du überhaupt den Konstruktor? Lass __init__ einfach weg.
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
rolgal_reloaded
User
Beiträge: 312
Registriert: Dienstag 24. Oktober 2006, 19:31

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
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.
Zuletzt geändert von BlackJack am Samstag 2. Dezember 2006, 17:53, insgesamt 1-mal geändert.
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

Wegen der Argumente. Dein Konstruktor nimmt keine an, dict() schon.
->

Code: Alles auswählen

def __init__(self, *args, **kwds):
    dict.__init__(self, *args, **kwds)
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
rolgal_reloaded
User
Beiträge: 312
Registriert: Dienstag 24. Oktober 2006, 19:31

@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
Zuletzt geändert von rolgal_reloaded am Samstag 2. Dezember 2006, 18:11, insgesamt 1-mal geändert.
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

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".
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
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.
rolgal_reloaded
User
Beiträge: 312
Registriert: Dienstag 24. Oktober 2006, 19:31

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...
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

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.
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

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.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
rolgal_reloaded
User
Beiträge: 312
Registriert: Dienstag 24. Oktober 2006, 19:31

@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
rolgal_reloaded
User
Beiträge: 312
Registriert: Dienstag 24. Oktober 2006, 19:31

...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
rolgal_reloaded
User
Beiträge: 312
Registriert: Dienstag 24. Oktober 2006, 19:31

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
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

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.
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
rolgal_reloaded
User
Beiträge: 312
Registriert: Dienstag 24. Oktober 2006, 19:31

@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.
Antworten