Seite 1 von 2

Kann man sich auf dictionary Unordnung verlassen?

Verfasst: Donnerstag 24. Januar 2013, 10:33
von mutetella
Hallo,

ich suche gerade nach einer geeigneten Struktur, um Attributnamen samt jeweiligem Werttyp zu hinterlegen. Jetzt weiß ich nicht, ob die dictionary Methoden 'keys' und 'values' immer die selbe Reihenfolge liefern:

Code: Alles auswählen

>>> APPT_ATTR
{'begin': 'datetime', 'end': 'datetime', 'longtext': 'str', 'title': 'str', 'owners': 'list', 'categories': 'list'}
>>> APPT_ATTR.keys()
['begin', 'end', 'longtext', 'title', 'owners', 'categories']
>>> APPT_ATTR.values()
['datetime', 'datetime', 'str', 'str', 'list', 'list']
Ansonsten würde ich die Namen und die Typen in 2 separate tuple stecken. Gefällt mir allerdings nicht, weil man da schon gut aufpassen muss, nichts durcheinander zu bringen... :)

mutetella

Re: Kann man sich auf dictionary Unordnung verlassen?

Verfasst: Donnerstag 24. Januar 2013, 10:44
von /me
mutetella hat geschrieben:Jetzt weiß ich nicht, ob die dictionary Methoden 'keys' und 'values' immer die selbe Reihenfolge liefern:

Code: Alles auswählen

>>> APPT_ATTR
{'begin': 'datetime', 'end': 'datetime', 'longtext': 'str', 'title': 'str', 'owners': 'list', 'categories': 'list'}
>>> APPT_ATTR.keys()
['begin', 'end', 'longtext', 'title', 'owners', 'categories']
>>> APPT_ATTR.values()
['datetime', 'datetime', 'str', 'str', 'list', 'list']
Im Zweifelsfall rufe die Informationen zusammen ab und zerlege sie dann.

Code: Alles auswählen

keys, values = zip(*APT_ATTR.items())

Re: Kann man sich auf dictionary Unordnung verlassen?

Verfasst: Donnerstag 24. Januar 2013, 11:00
von mutetella
@/me
Vielen Dank! Genau das Ergebnis versuche ich schon die ganze Zeit mit einer LC und 'items()' zu basteln. Ist nicht das erste mal, dass ich nicht an 'zip' denke. Das muss am Namen liegen, ich verbinde mit 'zip' einfach was anderes...

mutetella

Re: Kann man sich auf dictionary Unordnung verlassen?

Verfasst: Donnerstag 24. Januar 2013, 12:04
von BlackJack
@mutetella: Deine Frage wird in der Dokumentation beantwortet: dict.items(). `zip(*d.items())` ist also nicht nötig.

Re: Kann man sich auf dictionary Unordnung verlassen?

Verfasst: Donnerstag 24. Januar 2013, 13:04
von mutetella
@BlackJack
Ok... :oops: Um es mit lunars Worten auszudrücken: RTFM! :)

Was ich dabei allerdings nicht so wirklich verstehe:
items() hat geschrieben:... listed in an arbitrary order which is non-random, ...
Eine willkürliche Sortierung die nicht zufällig ist? Bezieht sich non-random darauf, dass es eben sehr wohl eine Sortierung gibt,
items() hat geschrieben:... depends on the dictionary’s history of insertions and deletions.
auf die aber nicht näher eingegangen wird und deshalb willkürlich erscheint?

Und zuletzt (auch wenn es sich somit erledigt hat):
Ließe sich /me's Lösung auch mit einer LC machen? Das lässt mir einfach keine Ruhe... :?

mutetella

Re: Kann man sich auf dictionary Unordnung verlassen?

Verfasst: Donnerstag 24. Januar 2013, 13:11
von /me
BlackJack hat geschrieben:@mutetella: Deine Frage wird in der Dokumentation beantwortet: dict.items(). `zip(*d.items())` ist also nicht nötig.
Das liefert aber unterschiedliche Dinge. Ich war davon ausgegangen, dass zwei getrennte Listen/Tupel erstellt werden sollten.

d.items() lässt sich aber auch problemlos als zip(*zip(*d.items())) ausdrücken. :mrgreen:

Re: Kann man sich auf dictionary Unordnung verlassen?

Verfasst: Donnerstag 24. Januar 2013, 13:23
von BlackJack
@/me: Ich habe nicht gesagt er soll `dict.items()` verwenden, sondern das dort seine Frage beantwortet wird wie sich `dict.keys()` und `dict.values()` verhalten. Bei den beiden Methoden steht in der Doku der Hinweis auf die Bemerkung in der Doku zu `dict.items()`.

@mutetella: Die Ordnung ist nicht zufällig, aber es wird halt auch nicht so richtig verraten wonach sie sich richtet, weil das ein Implementierungsdetail ist. Konkret bei CPython ist ein `dict` als Hashtabelle implementiert.

Re: Kann man sich auf dictionary Unordnung verlassen?

Verfasst: Donnerstag 24. Januar 2013, 13:27
von /me
BlackJack hat geschrieben:@/me: Ich habe nicht gesagt er soll `dict.items()` verwenden, sondern das dort seine Frage beantwortet wird wie sich `dict.keys()` und `dict.values()` verhalten. Bei den beiden Methoden steht in der Doku der Hinweis auf die Bemerkung in der Doku zu `dict.items()`.
Mit dem Hinweis, dass das für CPython gilt. PyPy scheint sich allerdings ebenso zu verhalten - und es wäre auch merkwürdig wenn man es unterschiedlich implementieren würde -, aber eine Garantie für alle Plattformen und für alle folgenden Versionen hast du nicht.

Re: Kann man sich auf dictionary Unordnung verlassen?

Verfasst: Donnerstag 24. Januar 2013, 13:35
von mutetella
/me hat geschrieben:... aber eine Garantie für alle Plattformen und für alle folgenden Versionen hast du nicht.
Wobei der Grundsatz, dass 'keys()' und 'values()' jeweils eine Liste in derselben Reihenfolge zurückgeben, wird zwischen diversen Plattformen und Versionen ja wohl eingehalten werden, oder?
Andernfalls wäre Deine 'zip'-Lösung wohl das Sicherste...

mutetella

Re: Kann man sich auf dictionary Unordnung verlassen?

Verfasst: Donnerstag 24. Januar 2013, 14:04
von /me
mutetella hat geschrieben:
/me hat geschrieben:Wobei der Grundsatz, dass 'keys()' und 'values()' jeweils eine Liste in derselben Reihenfolge zurückgeben, wird zwischen diversen Plattformen und Versionen ja wohl eingehalten werden, oder?
Und warum steht dann bei items() in Fettschrift: "CPython implementation detail"?

Wenn das in der Vergangenheit vielleicht seit langer Zeit immer und überall so war, dann kannst du natürlich durchaus glauben, dass sich das in Zukunft auch nicht ändert. Du bewegst dich dann allerdings nicht im Bereich der Informatik, sondern in dem der Religion. Immerhin könntest du dann darum beten, dass keiner die Implementierung ändern möge ...

Re: Kann man sich auf dictionary Unordnung verlassen?

Verfasst: Donnerstag 24. Januar 2013, 15:06
von BlackJack
@/me: Weil das was *in dem Kasten* steht ein CPython-Implementierungsdetail ist. Die Garantie um die es geht steht aber *nach* dem Kasten und gilt für alle Implementierungen.

Re: Kann man sich auf dictionary Unordnung verlassen?

Verfasst: Donnerstag 24. Januar 2013, 16:33
von snafu
Dies hier ist der Schlüsselsatz:
If items(), keys(), values(), iteritems(), iterkeys(), and itervalues() are called with no intervening modifications to the dictionary, the lists will directly correspond.
Ein `dict`-Objekt - egal in welcher Python-Variante implementiert - muss also laut Sprachspezifikation garantieren, dass die Rückgabewerte der o.g. Methoden passend zueinander sind - sich also in ihrer Reihenfolge nicht verändern. Dies gilt solange, wie keine Veränderung am Wörterbuch vorgenommen wird. Ich denke, dies ist der Punkt, auf dem Blackjack aufmerksam machen wollte.

Zur Art der Reihenfolge wird halt nur gesagt, dass es in anderen Python-Implementationen durchaus eine andere Reihenfolge bei der Ausgabe geben kann, was aber nichts mit der außerhalb des Kastens genannten Garantie zu tun hat. Theoretisch wird nichtmal garantiert, dass zwei unterschiedliche `dict`-Instanzen mit der selben Änderungshistorie zwangsläufig die selbe Reihenfolge ausgeben müssten.

Man sollte sich also nicht auf die Reihenfolge im Detail verlassen, sondern nur darauf, dass sie sich wie gesagt nicht ändert, solange man nichts am Dictionary verändert.

Re: Kann man sich auf dictionary Unordnung verlassen?

Verfasst: Donnerstag 24. Januar 2013, 16:42
von /me
BlackJack hat geschrieben:@/me: Weil das was *in dem Kasten* steht ein CPython-Implementierungsdetail ist. Die Garantie um die es geht steht aber *nach* dem Kasten und gilt für alle Implementierungen.
Das stimmt natürlich. Ich hatte die Frage nach "diversen Plattformen und Versionen" so verstanden, dass ein identisches Verhalten über die Grenzen der aktuellen Python-Version erwartet wird. Innerhalb eines gegebenen Python-Biotops ist man definitiv auf der sicheren Seite.

Re: Kann man sich auf dictionary Unordnung verlassen?

Verfasst: Freitag 25. Januar 2013, 19:44
von mutetella
Was soll ich machen? Es lässt mir keine Ruhe!!!

Ich versuche verzweifelt, folgendes in einer LC unterzubringen:

Code: Alles auswählen

>>> d = {'a': 'A', 'b': 'B'}
>>> result = [[], []]
>>> for key, value in d.items():
...     result[0].append(key)
...     result[1].append(value)
... 
>>> result
[['a', 'b'], ['A', 'B']]
Das einzige, das irgendwie in die Richtung geht war bisher das:

Code: Alles auswählen

>>> [[key for key, value in d.items()]]
[['a', 'b']]
Ich möchte jetzt gar nicht über Sinn oder Unsinn dieser LC reden... aber es muss doch irgendwie gehen...

mutetella

Re: Kann man sich auf dictionary Unordnung verlassen?

Verfasst: Freitag 25. Januar 2013, 19:49
von BlackJack
@mutetella: Nö, das muss nicht gehen. Eine LC erstellt Elemente für eine Liste. Du möchtest aber zwei erstellen.

Re: Kann man sich auf dictionary Unordnung verlassen?

Verfasst: Freitag 25. Januar 2013, 19:53
von Hyperion
mutetella hat geschrieben: Ich möchte jetzt gar nicht über Sinn oder Unsinn dieser LC reden... aber es muss doch irgendwie gehen...
Wieso "muss" es das? ;-)

Re: Kann man sich auf dictionary Unordnung verlassen?

Verfasst: Freitag 25. Januar 2013, 20:05
von cofi
Zwar keine LC aber auch kuerzer als eine:

Code: Alles auswählen

In [1]: d = {'a': 'A', 'b': 'B'}

In [2]: zip(*d.items())
Out[2]: [('a', 'b'), ('A', 'B')]
Ok, es sind Tupel ..

Re: Kann man sich auf dictionary Unordnung verlassen?

Verfasst: Freitag 25. Januar 2013, 20:41
von BlackJack
Nur noch mal damit es nicht in Vergessenheit gerät die eine offensichtliche Lösung:

Code: Alles auswählen

In [5]: d = {'a': 'A', 'b': 'B'}

In [6]: [d.keys(), d.values()]
Out[6]: [['a', 'b'], ['A', 'B']]

Re: Kann man sich auf dictionary Unordnung verlassen?

Verfasst: Freitag 25. Januar 2013, 22:25
von Sirius3
@Blackjack: sollte das Dictionary zwischen dem keys- und dem values-Aufruf verändert werden, bekommst Du Probleme:

Code: Alles auswählen

import time
import threading

d={'a': 'A', 'b': 'B'}

def add_c():
    time.sleep(.5)
    d['c']='C'
 
t=threading.Thread(target=add_c)
t.start();
print [d.keys(), time.sleep(1), d.values()]
# [['a', 'b'], None, ['A', 'C', 'B']]
@mutetella: Die offensichtliche Lösung, wie man LC nicht verwenden sollte:

Code: Alles auswählen

>>> d={'a': 'A', 'b': 'B'}
>>> keys=[]
>>> [keys,[keys.append(a) or b for a,b in d.iteritems()]]
[['a', 'b'], ['A', 'B']]

Re: Kann man sich auf dictionary Unordnung verlassen?

Verfasst: Freitag 25. Januar 2013, 23:01
von snafu
mutetella hat geschrieben:ich suche gerade nach einer geeigneten Struktur, um Attributnamen samt jeweiligem Werttyp zu hinterlegen. Jetzt weiß ich nicht, ob die dictionary Methoden 'keys' und 'values' immer die selbe Reihenfolge liefern:

Code: Alles auswählen

>>> APPT_ATTR
{'begin': 'datetime', 'end': 'datetime', 'longtext': 'str', 'title': 'str', 'owners': 'list', 'categories': 'list'}
>>> APPT_ATTR.keys()
['begin', 'end', 'longtext', 'title', 'owners', 'categories']
>>> APPT_ATTR.values()
['datetime', 'datetime', 'str', 'str', 'list', 'list']
Wieso nutzt du für die Werttypen eigentlich Strings? Geht doch eigentlch auch mit Klassen:

Code: Alles auswählen

{'begin': datetime, 'end': datetime, 'longtext': str, 'title': str, 'owners': list, 'categories': list}