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

Samstag 2. Dezember 2006, 18:44

@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

Samstag 2. Dezember 2006, 19:15

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

Samstag 2. Dezember 2006, 20:18

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

Samstag 2. Dezember 2006, 20:24

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

Samstag 2. Dezember 2006, 20:34

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

Samstag 2. Dezember 2006, 21:22

rolgal_reloaded hat geschrieben:@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.
Nein, wenn du "list(x.iterkeys)", oder sonnt ein Objekt mit ner Generator Methode, mit list, tumple, etc benutzt, dann iterieren die selber darüber, also ruft next ;)
Beispiel
tuple(x.iterkeys()), list(x.iterkeys()), for i in x.iterkeys():

lg

EDIT: Wenn du "selber" iterieren willst geht das so:
y = x.iteritems()
y.next()
y.next()
etc...
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Samstag 2. Dezember 2006, 21:28

Code: Alles auswählen

x = {"foo": "bar", "blub": "spam"}
print x
y = x.iteritems()
print y.next()
print y.next()
print y.next()
output:

Code: Alles auswählen

{'foo': 'bar', 'blub': 'spam'}
('foo', 'bar')
('blub', 'spam')
Traceback (most recent call last):
  [...]
    print y.next()
StopIteration
Es wird also bis StopIteration iteriert. Und nichts anderes machen list(), etc auch :)
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Samstag 2. Dezember 2006, 21:30

EDIT: Ach so: das dran eine liste rauskommt ist normal, weil list() alle Elemente die es vom Generator kriegt dort reinfügt.
rolgal_reloaded
User
Beiträge: 312
Registriert: Dienstag 24. Oktober 2006, 19:31

Samstag 2. Dezember 2006, 21:42

XtraNine hat geschrieben:EDIT: Ach so: das dran eine liste rauskommt ist normal, weil list() alle Elemente die es vom Generator kriegt dort reinfügt.
Danke, war etwas wirr das Ganze, aber ich glaube ich habs:
Durch die Listcomprehension wird list() aufgerufen, welches alle Elemente, die es vom Generator bekommt......,richtig?

edit: Da habe ich vor lauter Lösungen wieder mal alles durcheinander geworfen, naja, eigenltich egal, der Thread ist so oder so gelöst.

LG

rolgal_reloaded
Zuletzt geändert von rolgal_reloaded am Sonntag 3. Dezember 2006, 14:48, 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

Samstag 2. Dezember 2006, 22:55

Nein, list() ansich wird nicht aufgerufen. Die List comprehension gleicht einer for-Schleife:

Code: Alles auswählen

l = [f(x) for x in y]
ist das gleiche wie

Code: Alles auswählen

l = []
for x in y:
    l.append(f(x))
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Samstag 2. Dezember 2006, 23:00

Naja wie das genau intern abläuft weiß ich nicht. Die Antwort überlasse ich den Profis hier. Eins steht auf jeden Fall fest, das ``[]``, ``()``, ``list()``, ``tuple()`` genauso in der Lage sind zu iterieren wie z.B. ``for``.
Durch die Listcomprehension wird list() aufgerufen, welches alle Elemente, die es vom Generator bekommt......,richtig?
Ne nicht ganz: Für ``[]`` wird der Opcode ``BUILD_LIST`` aufgerufen. ``list()`` dagegen wird erste in den Globals aufgelöst und ruft dann den Opcode auf (Richtig, birkenfeld?). Die sorgen nun dafür das bei einem Generator die ``.next()``-Methode aufgerufen wird und gibt bei jeder Iteration ein Element wider, bis ein ``StopIteration`` ausgelöst wird und das iterieren beendet wird.

Aber wie gesagt, wie das ganz genau intern abläuft weiß ich nicht.

EDIT: Hier noch ein Thread wo Birkenfeld den unterschied zwischen {} und dict{} erklärt hat, was sich auch auf list() übertragen lässt: http://www.python-forum.de/topic-8119.h ... hlight=24h

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

Samstag 2. Dezember 2006, 23:07

XtraNine hat geschrieben:``list()`` dagegen wird erste in den Globals aufgelöst und ruft dann den Opcode auf (Richtig, birkenfeld?).
Nicht ganz: da brauchts keinen Opcode mehr, weil der Typ "list" ja direkt in C implementiert ist und daher nur die entsprechende C-API-Funktion aufruft.
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

Samstag 2. Dezember 2006, 23:53

birkenfeld hat geschrieben:Nein, list() ansich wird nicht aufgerufen. Die List comprehension gleicht einer for-Schleife:

Code: Alles auswählen

l = [f(x) for x in y]
ist das gleiche wie

Code: Alles auswählen

l = []
for x in y:
    l.append(f(x))
Ist mir klar, dann wird halt was äquvivalentes wie list() aufgerufen. Es wird in jedem Fall eine Liste erzeugt, die bewirt, dass sich iterkeys() usw. sich so verhält wie oben beschrieben. - ?

LG

rolgal_reloaded
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Samstag 2. Dezember 2006, 23:55

birkenfeld hat geschrieben:
XtraNine hat geschrieben:``list()`` dagegen wird erste in den Globals aufgelöst und ruft dann den Opcode auf (Richtig, birkenfeld?).
Nicht ganz: da brauchts keinen Opcode mehr, weil der Typ "list" ja direkt in C implementiert ist und daher nur die entsprechende C-API-Funktion aufruft.
Ah, ok, danke dir :) Damit solte das Mysterium geklärt sein.

BTW: @all: dis.dis(...) ist Super :D ^^

lg
Zuletzt geändert von sape am Samstag 2. Dezember 2006, 23:56, insgesamt 1-mal geändert.
rolgal_reloaded
User
Beiträge: 312
Registriert: Dienstag 24. Oktober 2006, 19:31

Samstag 2. Dezember 2006, 23:56

Inzwischen frage ich mich, ob es bei aller Eleganz die der Code von BlackJack hat, stilistisch nicht etwas seltsam ist eine Methode der Elternklasse mittels einer anderen Methode der Elternklasse zu überschreiben.

Das ist mir jetzt nur mal so durch den Kopf gegangen.

Ich habe aber nicht wirklich die Erfahrung und das KnowHow das wirklich zu beurteilen.

Vielleicht gibts noch andere Meinungen dazu.

LG

rolgal_reloaded
Antworten