Transcript: Was, wenn alles ein dict wäre?
Full episode transcript. Timestamps refer to the audio playback.
Ja, hallo liebe Hörerinnen und Hörer. Wir kommen beim Python-Podcast, Episode 36.
Heute wollen wir mit euch ein bisschen über die technischen Implementierungsdetails von Dictionaries reden.
Jochen ist natürlich wieder da. Hi Jochen.
Hallihallo, Dominik.
Dominik, genau. Und heute ist auch wieder Johannes dabei. Hi Johannes.
Hallo zusammen.
Ja, moin.
Ja, wir fangen wie immer ein bisschen News aus der Szene an und was uns sonst noch so einfällt und dann gehen wir so ein bisschen in das Thema rein.
Ja.
Ja. Also du wolltest
unbedingt noch über den Copilot reden, habe ich gehört.
Ich wollte das.
Ja, ich auch. Der Jochen ist derjenige, der immer
darüber sprechen möchte. Ja, wir haben schon zweimal
darüber gesprochen. Aber jetzt hat auch Jochen
ihn ausprobiert. Jetzt hat auch
PyCharm hat jetzt auch Copilot.
Deswegen, genau.
Genau, ich habe irgendwann die erlösende Mail von
GitHub bei mir bekommen, sodass ich jetzt im Beta-Programm
auch mit drin bin. Und genau, da muss ich das
natürlich direkt mal ausprobieren. Und ich hätte da eigentlich gar keine
so hohen Erwartungen, obwohl du immer schon so davon
vorgeschwärmt hast. Ja, du hast immer gesagt, ach, was für ein Krass,
ist ja völlig egal. Ja, das kann ja nicht, also wenn man
jetzt irgendwie so durchschnittlichen Code
davon irgendwie in den Leuten kriegt, das kann ja nichts
das kann ja nichts taugen.
Aber ich muss sagen, ich bin
doch sehr überrascht, dass das manchmal
wirklich, wirklich hilfreich ist.
Sogar Jochen findet das hilfreich.
Sogar Jochen findet es hilfreich. Ja, ich finde es auch sehr cool.
Also ich finde vor allem diese Autocompletion cool. Er lernt irgendwie
aus seiner eigenen Codepace und weiß so ein bisschen, was
du als nächstes vorhaben könntest oder er macht manchmal so einen guten
Vorschlag. Ist natürlich nicht immer,
ist auch nicht immer richtig, aber manchmal ist er staunlich richtig.
Ja. Ja und manchmal
findet man halt Dinge dadurch
erst, die man, also ich
mache jetzt manchmal auch so ein bisschen
JavaScript beziehungsweise TypeScript
und
manchmal weiß ich einfach nicht, wie Sachen
gehen. Also ich habe keine Ahnung, wie das geht
und dann fange ich irgendwie mit einem variablen Namen an
und dann kriege ich so einen ganzen
Codeblock und der tut genau das, was ich
eigentlich machen wollte.
Also du musst halt wirklich aufpassen, was für
Namen du den Dingen gibst. Wenn du den guten Namen gibst,
ist der viel besser, als wenn du schlechte Namen gibst.
Da muss man sowieso aufpassen,
und immer gute Namen finden. Genau, aber wenn man das dann halt
macht und dann auch einen guten Doxtrain schreibt oder einen Kommentar
dazu, dann lernt er sogar noch aus diesen Doxtrains,
aus den Kommentaren was dazu. Oder halt, also
was halt bei mir vorgefunden wird, ich mache halt den
Methodennamen beispielsweise oder den Klassnamen oder
die Funktion und die Argumente und
Type-ins und dann weiß er ziemlich oft, was
zu tun ist, wenn ich den Doxtrain noch mache.
Dann schreibe ich im Doxtrain rein, was er tun soll und dann
der Vorschlag, der ist schon echt gut.
Also auch, da gibt einer halt auch Implementierungsvorschläge
an, die man vielleicht nicht gedacht hat oder sowas schon.
Ja, also da,
das ist durchaus
aus sehr...
Und ich weiß, warum Jochen den gut selber...
Weil er sich ja immer selber am eigenen Code-Repo orientiert.
Er orientiert sich an Jochens eigenem Code und dann denke ich auch
natürlich immer, oh, was für ein toller Vorschlag.
Ja, ja.
Das hat den Stil.
Also,
Kritik würde ich sagen,
es ist auch besser geworden,
wenn man diese Nightly-Versionen nimmt.
Ich habe zuerst die Standard-Version genommen
und man kann halt die
aktuelle Bleeding Edge-Geschichte nehmen.
Die ist, finde ich, nochmal ein gutes Stückchen besser.
Was manchmal
nicht so gut funktioniert, also was, womit
Copilot halt irgendwie unerwarteter
Weise, weil man denkt, das ist eigentlich eine einfache Geschichte,
große Probleme
hat,
wo er das große Problem hat, ist Klammern.
Also die Klammern richtig zu setzen,
also zum Beispiel zu machen,
Klammern richtig zu, oder
halt irgendwie, dass das halt
nur Sinn macht, wenn es runde Klammern sind. Manchmal macht er auch
einfach eckige Klammern bei mir, so an Stellen,
wo Funktionen aufgerufen werden und dann
ist das natürlich, das funktioniert halt nicht.
Kannst du das nicht erklären,
Das ist doch irgendwie diese neuronalen Netze, weil die halt
nicht genügend Zustand für sowas haben, oder?
Ja, man muss denen halt irgendwie
die Syntax sozusagen irgendwie so einprügeln,
dass sie das halt nicht, dass das nichts Unscharfes ist
oder, aber das funktioniert vielleicht
nicht so richtig. Also meistens funktioniert das auch.
Ja, aber prinzipiell
hat dieses Netz ja kein Verständnis von
ich habe N-Klammern geöffnet und du musst jetzt
N-Klammern auch wieder schließen in der richtigen Reihenfolge.
Du kannst ja alle Vorschläge aussortieren, bei denen das
nicht stimmt oder du kannst ja danach noch auditieren oder sowas.
Ja, ja, klar, also es ist jetzt auch kein großes Problem
das ist halt irgendwie so ein bisschen erstaunlich
wo man sich denkt, naja, also das Schwierige, den
schwierigen Teil, den kann es eigentlich überraschend gut
nämlich irgendwie rausfinden, was man
da machen wollte und dann den Code schreiben
der zumindest so aussieht, als würde das richtig gut
und dann kommen halt so Dinge, wo man sagt
das kann ja fast, eine IDE kann das ja schon
so die Klammern richtig setzen
und das geht dann nicht mehr, ja gut, aber
ich meine, das sind Sachen, die wird man
halt mit der Zeit in den Griff kriegen, denke ich mal
und dann ist das schon
echt beeindruckend
Was man auch mal machen muss, ist so User-Daten
beispielsweise machst du irgendwie eine JSON
und dann machst du
einen Namen, eine E-Mail-Adresse oder so
und ein Passwort und dann machst du Autocomplete
und dann gibt dir halt eine Liste
von Usern irgendwie
mit seinem Passwort und so.
Das ist dann die Frage.
Das ist für den Demo-Benutzer perfekt.
Ja, oder sind die generiert oder echt?
Man weiß es aber nicht so genau, von wo die sind.
Das sind alle gelernt.
Ja, es ist wohl auch, wenn man so Zahlenfolgen eingibt,
dann gibt er einem interessante Instruktionen.
ein Screenshot gesehen, wo dann russische Funktionsnamen dazu kamen.
Also, okay.
Ja, ich bin ja mal gespannt, was dabei rauskommt.
Wenn man so was, man anfängt irgendwie so 3.1417...
Ja, ja.
Ab wie viel Nachkommastellung?
Ja, ja, vielleicht, vielleicht.
Also, ja, das ist ja...
Das ist noch keine AGI, das ist noch keine generelle Intelligenz, glaube ich.
Da habe ich letztens, ich komme vom Holzen aufs Stöckchen,
aber vielleicht ist das ja auch nicht so uninteressant,
und wieder einen ganz netten Podcast-Episode gehört mit Lex Friedman, wo Lex Friedman Stephen Wolfram interviewt hat.
Ja, der ist ja so ein Wunderkind und dann so ein bisschen hinter den Arm.
Eine sehr kontroverse Persönlichkeit.
Ja, polarisierend.
Warum? Jetzt musst du das genau aufklären direkt.
Ja, es gibt Leute, die lieben ihn total und der macht ja auch viele gute Sachen,
aber es gibt Leute, die hassen ihn auch total, weil der halt auch seine Meinung für sehr wichtig hält.
Achso, okay, ich wollte gerade sagen, wir wollen ja die Gründe und Anekdoten auch hören, es geht um seine Meinung, die er präsentiert
Ja, und er ist auch so ein, er hat so ein paar interessante Fixierungen, der findet, dass die ganze Welt aus State Machines besteht und muss alles mit State Machines machen
Und Rule 34 ist das einzige, was...
War das nicht Rule 38 oder so?
oder so. Ja, diese 30er-Regeln,
also das ist so eine Klasse von
State Machines
und die kannst du
durchnummerieren und die haben eine natürliche Ordnung
und dann findest du halt irgendwann
eine, die eine universelle Turing-Maschine ist
im Wesentlichen und
Stephen Wolfram sagt
halt mehr oder weniger, der schreibt ganze Bücher
darüber, was diese State Machine alles
kann und dass die das Universum enkodiert und das
ist natürlich
wenn du
wenn du die gesamte Wissenschaft umstellen willst auf State Machines.
Also ich habe immer noch keine Ahnung, was
Rule 38 ist, aber das Urban Digitry hat mir gesagt,
Rule 38 is a prison offense
in which someone is masturbating in public.
Ah ja, okay.
Also wenn du mal viel Spaß haben willst
und Private Mode an hast, dann google
doch mal nach Rule 34.
Rule 34, das ist glaube ich die
If it exists, there's porn of it.
Glaube ich. Das ist auch irgendwie
eine sehr wichtige Regel und tatsächlich stimmt sie
halt einfach immer. Aber
leider erstaunlicherweise.
as a type of font as a website for it.
Ach so, okay.
Das ist auch Rule 38.
Rule 30 sagen die.
Okay, aber das sind beides nicht die Regeln, die ich jetzt gerade meinte.
30 ist es.
Genau, um diese Dinger ging es
natürlich bei der Episode auch.
Ich finde das schon interessant.
Leute hatten
hohe Erwartungen an ihn, weil er war halt so ein Wunderkind.
Und dann ist aber irgendwie
dann doch nicht irgendwie so wirklich so
Einstein-mäßige
Ausmaße haben seine Theorien
da jetzt nicht angenommen, sondern
ein bisschen hinter den Erwartungen zurückgeblieben.
Aber tatsächlich ist er ja
genau eben der Meinung.
Er hat ja ein Buch geschrieben, das hat auch schon so einen Titel
New Kind of Science.
Den kann man ja auch nur nehmen, wenn man denkt, da hat man jetzt mal echt was
gefunden.
Er hat ein gewisses Selbstbewusstsein.
Aber er hat ja auch coole Sachen gemacht, also so ist es nicht.
und er ist halt auch super
ungeheuer produktiv, also es gibt so eine
er hat so ein Diagramm veröffentlicht von
wann er E-Mails schreibt und der hat eigentlich
immer 18 Stunden Tage und manchmal hat er
auch 24 Stunden Tage, also
er schlägt es einfach
durch Produktivität, diese ganzen
Kritikpunkte
Ja, also er hat ja auch so eine Firma, die macht
Mathematiker, auch eine super Software, also
ja
oder eben Wolfram Alpha, wie gesagt
Wolfram Alpha, genau, ja und
ja auch die Firma so zu nennen, also
und naja gut, aber
das ist, er macht ja wirklich
cooles Zeug, also so kann man eigentlich auch nichts sagen
und
das fand ich nur ganz interessant, weil es jetzt,
weil er auch da, da kam das Thema auch
auf Pi, ich meine, das ist ja auch
so eine Zahl, die einem ab und zu mal
irgendwie über den Weg läuft und er
Du meinst Tau halbe?
Ja, genau, ja stimmt, Tau
ist dann vielleicht etwas, was man häufiger noch braucht als Pi
und
genau, wie jeder
weiß, ist das Ding halt transzendent
rational und
hat eine Menge
super interessante Eigenschaften,
aber so fundamentale Sachen, die man jetzt, wo man
denkt, das müsste man doch eigentlich darüber wissen,
also wie zum Beispiel sowas wie
kommen denn
alle Ziffern in der
Dezimalbruchentwicklung von Pi mit der gleichen
Wahrscheinlichkeit vor? Also ist Pi normal
oder nicht? Das weiß man
halt nicht und zwar so gar nicht und hat auch
gar keine Ahnung, wie man das irgendwie hinkriegen könnte.
Dabei ist die Regel, die jetzt Pi erzeugt,
eben auch ziemlich einfach eigentlich.
und dann ist es doch irgendwie überraschend,
dass dabei eine Ziffernfolge rausfällt, die einmal
so total zufällig aussieht, wo man
nicht drüber sagen kann,
nicht mal die Verteilung der Ziffern
da drin sagen kann und die so aussieht,
als könnte man wirklich
nicht, man kann es halt auf nichts anderes reduzieren.
Man kann da drin, findet dann keine Muster.
Da kommt einfach
alles, was es überhaupt an Mustern irgendwie gibt,
kommt wohl offenbar daran vor.
Die Frage
ist halt, wie kommt aus so etwas,
aus so einer einfachen Regel, wie man
P bilden kann. Warum fällt da plötzlich so ein ganzes Universum raus?
Ja, das ist ja im Wesentlichen das, was der Wolfram auch sagt mit seiner Regel 30.
Das ist ja eine ganz simple Regel. Das ist die 30. die du ausprobierst, wenn du sie nach seiner
Ordnung machst und dann kommt so mordsmäßiges Chaos raus und alles, was du dir vorstellen kannst.
Das ist so eine generelle Sache
in der Mathematik. Irgendwann mache ich da auch mal noch einen längeren Diskurs drüber.
Dass man mathematisch gesehen aus sehr
einfachen Regeln, wo man denkt, ja, die
sind einfach genug, um sie im Kopf auszuführen,
Dinge
produzieren kann, die völlig
unabsehbar sind und völlig überraschend
auch, weil sie eben nicht mehr
sich an die Regeln halten, sondern weil sie dann irgendwelche
chaotischen Sachen produzieren und
das ist was
sehr Erschreckendes und das ist
aber auch gleichzeitig was sehr Schönes in der Mathematik,
weil man da eben Dinge finden kann,
die einen völlig überraschen, auch aus den
einfachsten Bausteinen raus.
Also, um das nochmal so zusammenzufassen,
Du hast gerade sich darüber beschwert, dass
die Wahrscheinlichkeitsverteilung
des Auftretens von einer Nachkommastelle
von Pi in der Gesamtsumme aller Nachkommastellen
von Pi, die bekannt sind,
nicht bekannt sind.
Also die kannst du ja nicht kennen.
Aber man weiß,
es könnte ja sein, dass irgendwann keine Neunen mehr
vorkommen, einfach gar keine mehr.
Ist das normalerweise so?
Nee, ist eben nicht normalerweise so.
Aber es könnte sein, wir können es nicht ausschließen.
Das ist die Sache, was der Jochen sagt, keine Ahnung
Ja
Und das ist überraschend, dass
man da so gar keine Ahnung hat, weil man denkt so
naja, das müsste man doch jetzt irgendwie, wenn man sich
irgendwie etwas an, wenn man die Regel wie Pi entwickelt
wird, hinschreibt und eine Funktion wie Pi ausrechnet
das ist wirklich so ein Verzeilen
muss man diese Zeilen nur ganz, ganz
lange und genau angucken und dann muss
einem doch klar sein, okay
da irgendwie, ne, neun, die kommen
genauso häufig vor wie alle anderen auch
Oder zumindest kommt immer mal wieder
einen neuen vor. Das ist ja schon eine Aussage,
die sehr schwer zu treffen ist.
Ja, aber das ist doch im Endeffekt, reduziert sich das
darunter auf das Halting-Problem, oder? Also,
wenn du das lösen kannst, dann kannst du auch das Halting-Problem
lösen. Was ist das Halting-Problem und was ist das Tau-Halbe?
Tau-Halbe
ist Pi.
Das gab es vor einer Weile mal, das Tau-Manifest,
wo jemand
behauptet hat, Pi ist eigentlich die falsche
transzendente Zahl.
Die richtige transzendente Zahl ist eigentlich Tau
und das ist
zweimal Pi, weil
dann ganz viele so quadratische Formen eben
einen Faktor 2 verlieren, der
diese Formen einheitlicher macht.
Es gibt auch ein Gegenmanifest
gegen dieses Tau-Manifest,
das quasi
das Gegenteil behauptet und sagt, das ist alles
Quatsch, weil es gibt genauso viele Dinge, die
mit Pi schöner aussehen als mit Tau.
Deshalb ist es nur ein Witz unter
Mathematikern, wo man Leute leicht
auf die Palme bringen kann.
Dann aber einfach nochmal kurz
die ganze Unbelegung. Was ist denn Pi?
Pi ist das Verhältnis zwischen dem Radius eines Kreises und der Fläche des Kreises.
Das heißt, wenn ich einen Kreis mit einem Radius 1 habe, dann hat er die Fläche Pi.
Und bei den meisten geometrischen Figuren ist es so, dass die Fläche sich relativ leicht berechnet.
Also wenn ich ein Quadrat habe und das hat Seitenlänge 1, dann hat es die Fläche 1.
und wenn ich
ein Dreieck habe, dann hat es die Fläche
1,5 mal 1.
Dann gibt es irgendwelche ganz leichten Formeln.
Beim Kreis ist es leider anders.
Da kommt eben die Zahl Pi raus
und die Zahl Pi ist eine transzendente Zahl.
Das heißt, die ist eine
nicht-rationale Zahl. Es gibt keinen Bruch,
der Pi
korrekt darstellen kann.
Es ist auch eine transzendente Zahl,
das heißt, die ist nicht algebraisch.
Das heißt, es gibt auch keinen Polynom,
was Pi als Lösung hat
und das macht es zu einer ganz besonderen Zahl
weil die Zahlen, die man normalerweise so kennt
Wurzel 2 und Wurzel 3 und Wurzel 5
und Wurzel 7 und
2 mal Wurzel 5 halbe
und so weiter, das sind alles algebraische
Zahlen, das heißt die sind Lösung von
irgendeinem Polynom und die haben dann eben diese
Eigenschaft, dass ich die in dieses Polynom
einsetzen kann und dann kommt 0 raus
Das geht mit Pi nicht
Es gibt für Pi kein Polynom
was Pi als Lösung hat
und deshalb ist es eine ganz besondere Zahl.
Nee, es gibt keins. Gibt es nicht? Also ist bewiesen, dass es nicht gibt?
Ja, weil es transzendent ist.
Und tatsächlich der Beweis, dass Pi
transzendent ist, ist eine sehr schwierige Sache.
Ist auch noch gar
nicht ungeheuer lange her.
Aber das
Ergebnis ist eben sehr wichtig, weil
das eine Klasse von Zahlen ist, von denen es
wesentlich
mehr gibt als von anderen Zahlen,
die für uns aber aus unserem menschlichen Verständnis her
sehr schwer erreichbar sind, weil wir eben
Brüche gewohnt sind und Wurzeln von
irgendwas, also
algebraische Zahlen. Das sind aber tatsächlich
so auf eine gewisse Art und Weise
die wenigsten reellen Zahlen.
Es ist eben
eins von diesen bekannten Beispielen
für eine Zahl, die sich anders verhält, als
man denkt. Und deshalb ist
sie in der Mathematik sehr wichtig, weil sie eben
eine transzendente
Zahl ist. Es gibt
noch ähnliche Zahlen, es gibt noch E.
Die Euler'sche Zahl?
Die Euler'sche Zahl, genau, und die hat nicht ganz so eine einfache Erklärung.
Sehr, sehr gut, Dominik.
Ja!
Die hat nicht ganz so einfache Eigenschaften, die ist nicht ganz so einfach zu erklären,
aber ist auch transzendent, ist auch, man weiß auch nicht, ob sie normal ist,
man weiß auch da die Verteilung der Sachen alle nicht.
Das heißt, diese Zahlen, die sind sehr, sehr schwer in den Griff zu kriegen,
obwohl es eigentlich sehr viele davon gibt.
und ja, das ist halt leider so.
Ja, und genau, also in gewisser Weise
haben die jetzt auch was mit eben
diesen ganzen theoretischen Informatikgeschichten
zu tun, weil sie sozusagen in gewisser
Weise
berechnungstechnisch
irreduzierbar sind, sozusagen.
Also man kann halt nicht,
eben, man muss es halt...
Man muss sie tatsächlich ausrechnen,
sonst kriegt man sie
nicht in den Griff. Und das Problem ist, das ist halt
teuer. Die auszurechnen, da muss man halt...
Ja, das ist ja auch so ein bisschen ein Sport,
dass die meiste
Anzahl Stellen von Pi ausgerechnet ist.
Ja, gab es sonst irgendwie wieder die Nachricht, dass da
die 60 Millionen Stellen oder weiß ich nicht
oder noch mehr, ich weiß gar nicht genau, wie viele...
Genau, also da kommt man dann halt wirklich sehr schnell in solche
Bereiche rein, wo es dann gar nicht mehr so sehr
um Prozessorleistung geht und gar nicht so sehr um
Smarthand geht, sondern da kriegst du dann so richtig die
Big Data Probleme. Wie schaffst du das auf einer Zahl
zu operieren, die 60 Milliarden Stellen?
Ich habe mich mal kennengelernt, der hat sich als Hobby
Aufgabe gemacht, Nachkommastellen von Pi
auswendig zu lehren, hat glaube ich die ersten 250
auch sagen können.
Okay, das ist schon mal nicht so schlecht. Ja, wir haben doch alle so einen Freund,
oder?
Ja,
es gibt auch irgendwie die Gesellschaft der
Freunde von Pi, glaube ich, und da muss man
irgendwie die ersten 100 Stellen auswendig können oder so,
damit man aufgenommen werden kann.
Vielleicht nochmal 142 von NMI,
geht das weiter?
Ja, 3,1,
das ist schon ungefähr richtig.
Wie du sagst, da gibt es auch so interessante Fälle, wo dann in irgendeinem Cut-Programm oder so
Das ist eine der bösesten logischen Bomben, von denen ich bisher so gehört habe
Dass jemand da den Wert von Pi irgendwie subtil verändert hat
So eher sechste, siebte Nachkommastelle oder sowas
Und dann waren halt alle Baupläne der letzten zehn Jahre alle falsch
Sehr schön
Kann man 3,12 sagen oder ist das auch immer falsch?
3,1415
ist so die
Standardweise, aber es ist eigentlich falsch, weil es geht ja mit
9 weiter.
Wenn man Pi
ich glaube auf 15 Stellen genau hat, dann
reicht es schon für alle physikalischen Sachen aus, weil
es dann irgendwie schon im Nanometerbereich ist und
so genau kannst du halt nicht mehr.
Und 3,142 ist zu grob noch
für sowas?
Ja, da hast du halt, wenn du
einen Kreis machst, der 10 Meter im Durchmesser
hat, hast du halt eine Abweichung
von einem Prozent. Also das ist dann schon
eine ganze Menge.
Jede
Programmiersprache hat eine konstante
eingebaut, die Pi heißt, Python übrigens
auch, math.py
und die hat
mehr Stellen, als man je in seinem
Leben brauchen wird.
Deshalb, völlig ausreichend.
Du hast gerade einen Bogen zu Python
gesagt, ich bin begeistert. Ja, wunderbar, oder?
Ja, sollten wir vielleicht irgendwie mal zurückkommen.
Das wird wieder so völlig unvorhergesehen, aber ich finde das eigentlich ganz interessant.
Das sollte doch heute eine sehr interessante Episode sein, oder?
Ja, da bist du die Leute halt durch.
Wenn man in die Möhre ran will, muss man auch ab und zu mal, keine Ahnung.
Man muss ja erst ausgraben, die Möhre.
Ja, rotten.
Gibt es noch was an News?
Ja, mit einem News, ich weiß nicht genau, ist irgendwas Interessantes passiert?
Django ist jetzt gerade die Prerelease-Kandidatin.
4.0 ist der
Pre-Release-Aufkommen.
Das hatten wir schon.
Ja, das letzte Mal hatten wir Alpha.
Ansonsten weiß ich nicht, gibt es eigentlich nichts.
Python 3.10 ist immer noch aktuell und immer noch
cool. Ja, meine letzte Folge hieß Python 3.10,
Jochen. Ja, gut.
Dann ist es trotzdem, ich wiederhole mich,
es ist immer noch aktuell und immer noch cool.
Ja.
Ja.
Es gab ganz lette
Artikel, einmal so über Python
im Bankenumfeld gab es einen, der
mit dem Bank-Python.
Großartig.
Wie, was?
Es gibt wohl eine Variante von Python,
die bei großen amerikanischen Banken eingesetzt wird
und die hat gewisse spannende Eigenschaften,
sagen wir mal so.
Wie heißt die?
Sie ist beschrieben als ein Fork des kompletten Bank-Python.
Bank-Python, jetzt habe ich es auf mich an.
Bank-Python.
Ja, okay.
Großartig.
Ich habe diesen Artikel gelesen und ich fand den super.
Ja, ich auch.
Und da sind auch so ein paar Ideen drin,
wo ich mir denke, ja,
da könnte man versuchen, sich eine Scheibe abzuschneiden.
An Oral History of Bank Python.
Genau.
L. Peterson.
Es sind auch
ganz viele Sachen drin, wo man sich denkt, naja, gut,
okay, gut, die sind halt in dem Jahr, in dem sie
den Fork gemacht haben, stehen geblieben und das war
vermutlich 1994 und
das ist jetzt halt so.
Aber es gibt
auch ein paar Sachen, die eigentlich sehr cool sind.
Also dieser globale State und dieses
globale Deployment und der Code
ist in der Datenbank und du kannst alles anfassen
und...
Barbara.
...sind schon viele Dinge, die man sich mal überlegen könnte.
Ja.
Jochen, den hast du vermutlich in meinen Weaknots gefunden, oder?
Ja, genau.
Ein bisschen Werbung machen für eigene Sachen.
Ja, richtig, genau.
Ja, ich hänge mit meinen Weaknots wieder total hinterher.
Ich muss da unbedingt was machen, aber ich habe irgendwie
keine Zeit, das ist schrecklich.
Das muss Teil des Prozesses werden.
Ja.
Das muss eine Gewohnheit werden.
Hast du hier nichts zu tun, Johannes?
Ich habe genügend zu tun, aber ich habe immer noch genügend Freizeit, dass ich Reddit lesen kann.
Und wenn ich statt Reddit Weaknotes schreibe, dann ist das doch ein Gewinn für uns alle.
Ja, das stimmt.
Ja, so viel Freizeit habe ich leider nicht.
Warte mal, Dominik, haben wir nicht erst Montagabend von 20 bis 24 Uhr Computerspiele gespielt?
Ist das Freizeit?
Nein, das ist Socializing.
Und es war erst um 20.36 Uhr haben wir angefangen.
Oh, ja gut, okay, dann.
Ja, und das, was wir lange gespielt haben, hat mich natürlich
nächsten Morgen noch fast gekostet.
Das ist ja auch klar.
Wir haben übrigens gespielt Max
Mechanized Assault and Exploration.
Okay.
Das ist ein Spiel, das kam das erste Mal,
ich weiß nicht, bei 98 raus.
Und so sieht's auch aus.
Es ist trotzdem
super. Es gibt eine, ja, ein MaxR.
Das ist eine Charakterversion. Wenn man die
Original, Anführungszeichen
Originalvideos und Sprites und sowas noch hat.
Das sieht gar nicht so schlecht aus, finde ich.
Naja, weil das Interface, also das ist
oft so, diese alten Sachen haben
oft gute Ideen, aber schlechte Interfaces.
Und das RTS ist eine unheimliche Komplexität.
Das ist aus der 96 schon, ehrlich.
So alt.
Fast so alt wie ich.
Wir haben es geliebt. Ja, und wir spielen das auch übrigens noch weiter,
allerdings, Johannes.
Ich dachte, wir spielen noch andere alte Spiele.
Ja, das werden wir auch mal schaffen, vielleicht nächstes Jahr.
Na gut, wie war das gleich noch mit Python?
Ja genau, dann machen wir jetzt
Python Dictionaries und so, ne?
Ja
Ihr wolltet heute über Dictionaries sprechen
Ja, richtig verstanden
Also was ist denn ein Python Dictionary?
Ein Wörterbuch, ein
Mapping von Dingen auf andere Dinge
Wie verstehst du denn ein Python Dictionary?
Also ich meine, der Jochen und ich, wir können uns gleich noch
über die Interna unterhalten und da gibt es viele spannende
Dinge, die man da besprechen kann
Aber Dominik, wie siehst du denn ein Python Dictionary?
Was ist denn für dich ein Python-Dict-Driven?
Ja, das ist erstmal ein geschweifte, geklammertes,
definiertes Objekt in Python, also das
kein Z ist, sondern das eine Zuordnung immer macht von
einem Key auf einen Wert
und wo halt der Lookup, also das, wenn man
nachgucken kann, sehr, sehr schnell geht, weil man schön
drauf zugreifen kann und dann gibt es direkt
einen Wert zurück, den es rausschmeißt. Das ist so, dass
wie im Python-Dict man ihn einfach, glaube ich, schnell benutzt.
Okay, Zuordnung von einem Key zu einem Wert.
Das heißt, ich könnte mir jetzt zum Beispiel
zum Key Dominic
deine Telefonnummer speichern.
und dann könntest du das
Phone Numbers nennen oder sowas und dann machst du das
gleich mit Jochen noch und ja. Und könnte ich mir aber nicht auch
deine Adresse dazu merken?
Ja, aber zu was? Also das ist ja
die Frage, wie du das strukturieren möchtest.
Da kann man ja beliebige
Objekte als Value hinterlegen.
Nee, das stimmt nicht. Achso, als Value schon, aber
Key als Key nicht. Nein, aber genau, als Value
hinterlegen, das heißt, da kannst du natürlich dann... Aber immer nur einen, oder?
Value, du kannst
einen Tupel reinpacken.
Okay, ich kann einen Tupel reinpacken, aber ich könnte mir jetzt nicht
2 mal zu dir zwei verschiedene Sachen merken.
Also das müsste ich dann selber machen.
Nee, tatsächlich. Also ein Key muss es
unique in einem.
Weil das ist ja in einem Wörterbuch
nicht so. Und in einem Telefonbuch ist
das auch nicht so.
Das ist so eine
Sache, die immer... Ich mache gelegentlich Python-Schulungen.
Übrigens im Dezember wieder. Naja, aber wahrscheinlich
ist dann so, dass wenn du das Lookup machst und dann Dominik
nachguckst und dann gibt es verschiedene Dominiks, dann hast du erst eine Liste
von Dominiks, die du zurückkriegst und in dieser Liste
stehen dann die einzelnen. Ja, aber ich kriege ja
und Jochen unterhalten sich über die Programmiersprache Python
das bekommt, dann ist ja der Zugriff auf ein Einzelmüller genau,
jetzt ist eigentlich nur eine Ebene tiefer.
Was ich da so tiefer drin verstanden habe,
ist, dass du irgendwie halt in den Speicher gemeldet wirst und das deswegen so schnell
ist, weil er dann einfach dann die Speicheradresse
nachschauen kann.
Ja, das ist ja die Magie des Hashtables.
Das Hashtable, das müssen wir auch gleich nochmal erklären,
was da ein Hashtable ist.
Was können denn Keys sein?
Weißt du das, Dominik? Weißt du das auswendig? Das ist total
spannend. Wenn ich den
Jochen frage, da weiß ich, dass der das weiß.
Ja, also ich weiß, was Strings
sein können, was Zupels sein können.
Ich weiß, dass es Integers sein können
Noch was?
Strings auch?
Ja, genau, Strings habe ich ja gesagt
Kann es auch ein Dictionary sein?
Nee
Doch, sind die hashable?
Und eine Liste?
Sind die hashable?
Das war schon eine sehr, sehr gute Frage
Die hashable
Das frage ich nicht, Dominik
Das weiß ich nicht
Die Regel ist
Tatsächlich ganz interessant
Ein Key von einem Dictionary muss etwas sein, was sich nicht verändern kann
Herrschable sind diese Typen alle
aber der Herrsch kann sich verändern
wenn sich das Objekt verändert
und deshalb
gibt es für Dictionary
für Liste gibt es Tuple
ich kann eine Liste nicht als Key verwenden, weil die sich verändern kann
ich kann aber ein Tuple verwenden und ein Tuple ist ja im Wesentlichen nichts anderes als eine Liste die sich nicht ver kann F Dictionaries und f Sets gibt es einen Datentyp der hei FrozenDict und FrozenSet
und das sind im Wesentlichen Dictionaries und Sets,
die sich nicht verändern können. Das heißt, wenn ich ein Set
als Key in einem Dictionary haben möchte, muss ich ein FrozenSet
draus machen. Und das ist auch so ein bisschen der einzige Sinn
für diese beiden Datentypen, dass du eben
ein unveränderliches Dictionary oder ein unveränderliches
Set haben kannst, um sie als
Key in einem Dictionary zu verwenden.
Und das machen wir, weil man ein Lookup haben will nach dem Motto,
wenn das da drin ist, dann gib mir dies.
Ja, oder
halt auch, wenn man sie wieder in ein Set packen möchte,
weil man möchte, dass da Schnittmengen
von Sachen bilden können oder feststellen
können, ob man das schon mal gesehen hat oder so.
Ja, oder die Reihenfolge spielt keine Rolle.
Das ist ja,
als Mathematiker
ist ein Set wie eine Liste ohne Reihenfolge.
und die interessante Reihenfolge
müssen wir uns auch merken, weil OrderedDict und sowas, weil das ja
früher nicht so ging, das glaube ich default ist.
Ja, muss man inzwischen nicht mehr. Früher musste man sich
OrderedDict immer merken, aber inzwischen sind alle Dicts
OrderedDicts, deshalb den Typ
OrderedDict gibt es noch, aber der macht irgendwie gar nichts mehr.
Ja, doch, doch, doch. Der hat noch einen reversed, aber
das ist alles. Ja, doch, der hat, die verhalten sich
unterschiedlich. Also
tatsächlich macht das durchaus Sinn.
Also man muss einfach mal, das ist vielleicht so ein bisschen,
vielleicht sollte man das nicht müssen, aber je nachdem
wie man Dict verhält,
wie sich das Dict verhalten
soll, das man verwendet. Also wenn man zum Beispiel
viele Insatz hat von Keys,
dann ist es besser, OrderDict
zu nehmen statt dem
Default-Ding. Also es gibt da
tatsächlich subtile... Warum, Jochen? Wie wächst das denn?
Wie wächst denn ein Dictionary?
Genau. Ich habe es vorhin nachgeguckt.
Soll ich es euch verraten?
Ja, verraten.
Ich hatte eh mal.
Ein Dictionary fängt an
mit null Buckets.
Wenn du ein leeres Dictionary hast, das ist tatsächlich speziell.
Das hat null Buckets, verbraucht 64 Byte.
Das ist übrigens unterschiedlich zwischen 32 und 64 Bit Maschinen, aber ich glaube, wir sind alle inzwischen auf 64 Bit angewandt.
Sobald ich eins einfüge, hat es acht Buckets.
Buckets sind Speicherplätze, erklären wir gleich noch, weil es eben zu dieser Hashmap gehört.
Und dann verdoppelt es sich jedes Mal, wenn es zwei Drittel voll ist.
Der Speicherbereich wird vorreserviert für alles, was wir reinhaben.
Genau, diese Datenstruktur, die heißt HashMap und die braucht leeren Platz, die kann nicht 100% voll sein und deshalb machen die halt immer eine Verdopplung, Verdopplung ist so eine Wachstumsstrategie, die gut funktioniert, auch bei Resizable Listen, die verdoppeln sich auch, das ist einfach so eine Wachstumsstrategie, die so eine gute Balance ist.
am besten wäre es, glaube ich, wenn man Wurzel 3
hätte als Wachstumsfaktor, das ist 2,3
oder irgendwas, aber dann hast du die ganze Zeit
krumme Zahlen und das ist auch nicht gut.
Ja, stimmt, das ist bei dem
Array-Modul,
bei dem eingebauten, das habe ich
mir mal näher angeguckt aus Gründen
und da ist das auch so,
weil das ist ja auch interessant,
das ist ja quasi sozusagen
wie eine Listefluss halt
statisch gefühlt, quasi, ja,
und man verbraucht tatsächlich nur den Platz,
also für den Integer braucht man halt nur,
je nachdem, das war natürlich bei 64-Bit.
Und da ist es auch so,
da kann man Append sagen hinten
und wenn man da was hinzufügt und
der Bereich der Memory-View innen
drin ist erschöpft,
dann verdoppelt sich das halt auch immer.
Ja, das ist eine klassische Strategie.
Okay, das bedeutet aber halt auch, man darf
sich nicht darüber
im Unklaren sein, so ein Dict-Journal verbraucht
relativ viel Speicherplatz. Wenn ich einen Eintrag
in ein Dict-Journal reintue, dann hat es direkt
240-Byte-Hauptspeicher verbraucht.
Das ist nicht ganz ohne
Wenn ich 6 Einträge
reintue, hat es direkt 480 Byte
verbraucht
Also es verbraucht relativ
viel Speicherplatz
Es geht hier nicht um Effizienz, sondern es geht um
Schnelligkeit
Und diese Schnelligkeit, die hat
Dominik schon angesprochen, es ist sehr schnell
Das heißt, es ist O von 1
Jeder Zugriff dauert immer gleich
lang, amortisiert
amortisiert über die Verdopplungen
weil wenn ich nämlich ein Dictionary habe, was sehr viele Einträge hat
und das verdoppelt sich dann, dann muss dieses Dictionary
angepasst werden
und eventuell verschoben werden
dann
kann es schon sein, dass es eine Weile dauert
aber amortisiert ist es auch von 1
jeder Zugriff, das heißt jeder Zugriff dauert
im Schnitt gleich schnell
also amortisiert bedeutet für Dictionary der gleichen
Länge?
Nee, das bedeutet im Schnitt
im Durchschnitt bedeutet das
jeder Zugriff braucht ungefähr gleich lang
und das ist eine konstante Zahl.
Es gibt einzelne, die dauern ein bisschen länger.
Ich habe diesen Worttransfer von amortisiert auf dem Schnitt hinbekommen.
Wenn du eine große Anzahl
Zugriffe machst, dann
ist die
Dauer
so, als ob du eine konstante
Okay, genau, weil das Umbauen quasi
Grenzwert Null hat.
Das Umbauen passiert selten genug.
Genau, dass es Grenzwert Null hat.
Deswegen wird es amortisiert.
Okay.
Also O von 1. Also O von 1 bedeutet, es ist kein Problem.
Genau, O von 1. Wir O von 1 schreiben.
Also wenn ich ein Element einfüge, dann dauert es O von 1.
Und wenn ich ein Element rauslese, dauert es auch O von 1.
Und beim Lesen ist es immer O von 1.
Also das ist nicht nur amortisiertes O von 1, sondern das ist O von 1.
Also das heißt tatsächlich, um nochmal einhören,
das so ein bisschen näher zu bringen,
dieser Zeitnotation, Big O, noch nicht so viel anfangen.
O von 1 bedeutet, es dauert quasi keine Zeit, das zu tun.
Doch, doch.
Es dauert immer gleich lang.
Es ändert sich mit der Menge.
der, also normalerweise, wenn du jetzt sagen,
O von 1 im Vergleich zu O von N
ist jetzt, bedeutet
das sozusagen, wenn deine
Eingabedatenmenge
halt nicht
N ist, dann wenn du eine Hashmap
hast, dann ist es halt immer noch O von, ist immer noch konstant.
Genau, aber das wäre... Aber bei was
andere, bei einer Liste ist es halt O von N, wenn du
darauf zugreifen willst, weil du musst ja alle Dinge angucken,
ob es das jetzt ist, was du haben wolltest oder nicht.
Aber O von 1 bedeutet halt, ich kann halt nichts
machen.
Also es ist halt so
und das ändert halt, genau, das heißt
also auch egal ob kleine oder große Datenmengen,
völlig wurscht, was da passiert und das heißt
der steht quasi in meiner Berechnung, ob ich da irgendwas
Algorithmus verbessern kann, zu vernachlässigen, weil das keine Rolle spielt,
ob das, das muss halt einfach so.
Ja, genau.
Und das ist was ganz witziges,
ich hatte mal
in der Python-Schulung einen Teilnehmer,
der da auch gut mitgemacht hat
und der war empört darüber,
das ist unmöglich, das kann gar nicht gehen,
das kann gar nicht sein.
Und dann haben wir tatsächlich einen kleinen Benchmark,
geschrieben und haben das einfach mal ausprobiert.
Und das ist eine sehr schöne Übung.
Das ist eine sehr schöne Sache, einfach mal
auszuprobieren, wie sich diese
Laufzeiten verhalten. Wie lange es dauert,
1000 Einträge einzufügen und
10.000 Einträge einzufügen und 100.000
Einträge einzufügen und die dann auch wieder rauszulesen
im Vergleich zu
einer Liste.
Also du hast einfach quasi die Keys
mit Brackets
dann gesetzt in einer Schleife oder was?
Genau. Und habe einfach
die Zahlen von 1.000 bis 10.000 als
Key und als Value, das spielt ja keine Rolle, wenn wir nur die Größe wissen wollen. Das ist dann ein sehr
unnützes Dictionary, weil das halt einfach, wie man sagt, zum Key 1 gehört
der Wert 1 und zum Key 10 gehört der Wert 10.
Aber wenn es nur ums Benchmarken geht, dann ist das eine einfache Sache.
Und bei einer Liste genauso, einfach mal eine Liste aus zwei Tupeln
zusammengebaut. Und dann in dieser Liste einen bestimmten
Eintrag suchen, ist halt O von N, weil durch diese Liste
von vorne bis hinten durchgegangen werden muss.
Und wenn ich jetzt den Eintrag 100 suche,
dann muss ich halt das erste Element angucken und fragen,
ist das 1? Nein.
Und das zweite Element, ist das 1? Nein.
Und das muss ich dann 99 Mal
machen. Beim 100. sage ich, ist das Element 100?
Und dann sage ich ja
und dann bin ich fertig. Bei einem Dictionary,
Hashmap, wir sprechen gleich, wie das
funktioniert. Im Moment Magie.
Dann
passieren halt 10 Rechenschritte
und dann steht da, okay, du hast
jetzt so 100, hast du dir 100 gemerkt.
und es spielt keine Rolle, ob das Dictionary
einen Eintrag hat, nämlich nur diese 100
oder ob es eine Million Einträge hat, das ist
immer gleich schnell. Genau, aber was
jetzt da interessant ist, hat zwei Dinge, also erstens
wie man dann, also das ist eigentlich ein falscher Datentyp,
aber wie man dann in der Liste das vielleicht
schneller suchen könnte, weil also theoretisch
könntest du ja in der Liste quasi auch daraus eine
Hashtable bauen, irgendwie aus allen Einträgen dieser Liste
einfach da nachgucken, wenn die Hashtables
sind, diese Datentypen oder sowas, ja genau
und dann halt überlegen sich irgendwie den Algorithmus,
wie man relativ schnell die Dinge in dieser Liste findet,
ohne, dass man halt über die ganze Liste
iterieren muss. Ja, aber da brauchst du eine andere
Datenstruktur. Wenn du nur die Liste hast, dann muss
die Liste an sich garantiert
dir das nicht. Die garantiert dir nur, dass es Elemente
in einer Abfolge gibt. Die nächste Frage wäre jetzt, wie halt
in der Stickt, was ja auch im Prinzip
eine Liste von Keys ist, jetzt erstmal so
in der Syntax, wie das dann in den Speicher
so reinkommt, dass man diesen Lookup machen
kann, dass man halt quasi
aus dem Wert des Keys
eine Speicheradresse bekommt quasi.
Ich möchte noch dazu sagen,
Ich möchte noch dazu sagen, du hast jetzt gesagt, das ist eine Liste von Keys, dem stimme ich so nicht ganz zu. Es gibt nämlich da drei Ansichten drauf. Es gibt die Keys, das ist ein Set, das ist eine Menge, die hat auch keine Reihenfolge.
schon, aber
früher nicht
also hat eine Reihenfolge
ja, aber es ist ein Set, weil
im Sinne von
die Reihenfolge
ist nicht
die Reihenfolge, die reingeschrieben worden sind
ja, das ist die Reihenfolge
die jetzt halt
irgendwann dazukommen sind, aber
wenn wir ein Dict von Python 3.4 nehmen, dann hat es
keine Reihenfolge
also in Python 3.5 kam ein Ordered Dict
Ne, also ein Ordered Stick gab es schon immer, aber
dass das sortiert ist, das kam in
3.6 dazu, wurde aber noch nicht garantiert
und ab 3.7
ist es halt auch garantiert, dass es so bleibt
Also in 3.6 war es ein
Implementierungsdetail und in 3.7 gehört es
zur Spezifikation
Aber wenn man sich so
ein ursprüngliches Stick mal anschaut
dann sind die Keys eigentlich ein Set
Die haben keine Reihenfolge
in dem Sinne
und die können auch keine Duplikate
enthalten. Und das ist genau das, was eine Menge ausmacht.
Also quasi ein Set of Sorted Set.
Ja, wobei die Sortierung
die
Reihenfolge des
Einfügens ist. Dann gibt es
die Values. Das ist auch ein View
auf diese Daten, die in dem
Diktator drin sind. Das sind halt die Werte, die da gespeichert sind.
Das ist im Wesentlichen eine Liste.
Die Liste der Werte. Und dann
gibt es noch die Items.
das ist eine Menge aus Tupeln, die jeweils Key und Value enthalten
und für mich sind die Items so ein bisschen das, was das Dictionary ausmacht
das ist das, was da drin ist
also damit kann man ja quasi auch über so ein Dictionary etablieren oder sowas
man kann es einfach als Methode dot notated aufrufen
und dann kannst du quasi for Key Value in Dict.Items
genau, for Key Value in Dict.Items
das ist so ein Muster, das sieht man ganz häufig, weil man da einfach durch
quasi durch das gesamte Dictionary durchgeht
Man könnte auch
sagen for key in dictionary
und dann sich jeweils
den Value holen, weil es ist ja
O von 1
Das kostet ja so gesehen
algorithmisch nichts
Das kostet ausführungsweise schon was
Wenn du eine Vorschleife machst über alle
dann ist das halt schon O von N
sozusagen
Nur im Einzelfall halt nicht
Aber die Value nochmal rauszuholen, wenn du die schon hast
Genau, also die
O-Notation von for key value
in DictItems
irgendwas tun und
for key in Dictionary
und dann den Value als Dict von
Key holen, ist identisch.
Aber die Laufzeiteigenschaften
sind natürlich für den zweiten Fall schlechter,
weil ich dann jedes Mal nochmal in das Dictionary
rein muss. Natürlich nur für einen
konstanten Faktor.
Aber konstante Faktoren.
Ja, konstante Faktoren.
Also wenn etwas nur
zehnmal langsamer ist, das ist auch ein konstanter
Faktor.
Macht schon einen Unterschied.
Ist schon ein Unterschied, ja.
Ja.
Genau.
Wie kann man denn Dicks bauen? Wisst ihr das?
Ich habe vorhin einen ganz coolen Trick gelernt.
Es gibt ja mehrere Wege,
Dictionaries zu bauen.
Ja, was meinte du?
Syntaxmäßig, jetzt gescheuchte Kammer oder
Dicht von... Wie ich ein Dictionary erzeuge.
Also du kannst es natürlich einmal machen als Dictionary
Contraintion, indem du sagst,
gescheuchte Kammer, Key,
Value, oder du machst
hat einfach die Definition einfach in den eckigen
Kammern, schreibst dann den Key und den Value hinterher
oder du schreibst eine Liste von
Keys und Values mit
Gleichzeichen dahinter und machst dann Dict raus.
Also Dict of.
Ja genau, das ist der normale, also das ist der
Konstruktoransatz.
Du kannst die Keys auch in der Schleife
einfach hinzufügen.
Du kannst auch irgendwie, keine Ahnung,
Tupel-Unpacking oder sowas,
die ganzen Adrekte reingieben
mit so Sternchen, Sternchen, Quarks und Tacks.
bzw. wenn du eine Sequenz von Tupeln reingibst, von zwei Tupeln, dann nimmt er die automatisch.
Eine Methode, die ich gerne verwende, ist dict.fromKeys.
Was macht das?
Naja, du gibst halt eine Liste von Keys und dann halt vielleicht einen Default-Wert oder so
und dann erzeugt er das Ding dann raus mit diesem einen Factory-Methoden-Aufruf von dem Dict.
Default-Dict gibt es noch irgendwie?
Das ist schon etwas anderes.
Müssen wir nachher noch drüber sprechen.
Das ist nämlich auch eine spannende Sache.
Ich möchte noch einmal kurz zu der Comprehension zurückkehren,
weil die ist nämlich was sehr, sehr, sehr Cooles.
Und die ist was, was auch für Leute, die
das nicht kennen, super schwer zu verstehen ist.
Diese Dictionary Comprehension ist eine der
coolsten Wege, die es gibt,
so ein Dictionary zu bauen, weil es halt im
Wesentlichen diese Schleife, die man dazu
braucht, in das Dictionary reintut.
Also in die Konstruktion
und das ist was
sehr, sehr mächtiges. Die Syntax davon
jetzt hier im Podcast zu besprechen ist vielleicht...
Nee, mach nicht so viel, das muss man sich angucken.
Das muss man sich ansehen, aber das ist auf jeden Fall was, was man
ansehen kann. Ich habe vorhin noch einen
sehr coolen Trick gelernt und das ist DictSip.
Also wenn ich eine Liste von
Keys habe und eine Liste von Values,
dann kann ich die sippen und dann
ein DictSignal draus machen.
Das geht aber nur für gleich lange
Listen, ne?
Sip nimmt auch unterschiedlich lange Listen,
und schneiden dann halt den Rest ab.
Aber das ist, glaube ich, nicht der Sinn der Sache.
Der Sinn der Sache ist, du hast schon die Keys und du hast schon die Values,
aber in zwei Händen und mit Zip kannst du sie
in eine schöne Reihenfolge bringen,
die du schnell...
Einmal Reißverschluss, bitte.
So, wie kann man denn da Sachen wieder rauskriegen?
Dominik, weißt du, ich frage dich jetzt ab.
Ich finde das total gut.
Was meinst du?
Wie komme ich an die Werte wieder dran?
Ja, du kannst einfach...
Wenn ich jetzt ein Telefonbuch habe,
wie kriege ich deine Telefonnummer raus?
Du machst halt zum Beispiel entweder ein Get oder halt mit der
Brackets-Syntax ziehst du die direkt raus.
Bei Get kriegst du den Default-Wert
zurück und du kriegst einen
Error, wenn du
daraus einfach so ein Key zu lesen ist, das es nicht gibt.
Genau, wenn du es mit eckigen Klammern machst, kriegst du
im besten Fall einen Key-Error.
Der heißt tatsächlich Key-Error, also
wenn man das abfangen möchte, ergibt es das.
Genau, also beim Get kannst du halt dann den Default dranhängen.
Es gibt noch zwei andere coole
Attribute, die heißen
Pop und PopItem.
Ja.
Und die sind quasi
destruktiv, sie sind destruktiver Zugriff.
Wenn ich sage,
dictionary.pop.dominic,
dann heißt es,
entferne den Eintrag für Dominic,
aber gib mir den Wert auch noch zurück.
Wie bei einer Liste.
Wie bei einer Liste, genau. Also, ja gut, halt mit diesem
Key-Zugriff. Bei Pop muss ich immer
den Key sagen, bei einer Liste müsste ich den Index
sagen. Genau.
Oder er gibt dir den ersten Wert.
was natürlich beim Dick nicht geht, weil das nur einer ist
genau, das heißt, Dick.pop muss
immer einen Key haben, es gibt da keinen
ersten oder letzten oder wie auch immer
also das kann ich nicht machen, aber es gibt
PopItem
und PopItem
das macht Lifo
LastInFirstOut
das heißt, es gibt dir tatsächlich den
letzten Eintrag, der
hinzugefügt wurde, zurück als Item mit Key und Value
ach, dann braucht man den Key nicht mehr, das ist natürlich
interessant, da kann man bestimmt... als Key und Value
das ist schon sehr cool
Das heißt, du kannst
so eine While-Schleife machen und kannst
dieses Dictionary sozusagen abarbeiten.
Ja. Und hast dann so eine Art
Dictionary-Queue. Und das ist
eine praktische Sache, die ich erst
heute gelesen habe. Ja, sehr schön.
Ja, ne, hab ich auch so noch nicht verwendet, aber
da fallen mir auch direkt viele Sachen zu ein, die man
damit cool machen kann.
Ja, wo man so ein Dictionary
zerlegen kann.
Ja, also es gibt noch
Set Default.
Das ist, ich weiß nicht,
und man weiß, Leute, erzählen sollte das, was die Methode noch gibt.
Das darf man nicht sagen.
Naja, die ist eigentlich nicht gut.
Also die liefert halt auch quasi das
zurück, aber mit einem
Default-Wert, den man dann noch angeben kann,
wenn das nicht existiert.
Ja, stimmt.
Wo ich anfange, das erklärt sich mir schon ein, dass das
vielleicht keine gute Idee ist.
Es ist, glaube ich, besser, da direkt ein Default-Dict zu hören.
Genau, das ist auch die Empfehlung, sollte man halt heutzutage
eher Default-Dict nehmen.
Oder ein Get und dann den Wert setzen.
Wolltest du noch was?
Was ist ein DefaultDict?
Dafür müssen wir erst wissen, was ein DefaultDict ist.
Dann erzähl mir, was ein DefaultDict ist.
Ein DefaultDict ist ein Dictionary,
eine Unterklasse von Dictionaries.
Das keine Keys hat, aber wenn du einen Key abrufen willst,
den es noch nicht gibt, dann gibst du den DefaultWert zurück.
Genau. Du sagst eben,
welchen Standardwert es haben soll und wenn du
einen Key abrufst, den es noch nicht gibt, kriegst du den Standardwert.
Und da gibt es drei
große Varianten davon.
Die erste ist die Lambda-Variante, wo du
eine Funktion reingibst,
die dann diesen Standardwert erzeugt
und das ist sozusagen
die allgemeine, das ist DefaultDict
du musst dem DefaultDict irgendeine sogenannte Factory
geben, damit er diesen Wert erzeugen kann
und da kannst du jede beliebige Funktion reintun
meistens ist das halt irgendeine kleine Lernintervention
aber es gibt schon zwei Funktionen
die du da verwenden kannst, nämlich List und Int
die nützlich sind
also wenn du DefaultDict
Klammer auf, List Klammer zu machst
dann heißt das, das ist ein Dictionary
und wenn du da einen Key abrufst
dann gibt er dir, wenn du noch nichts eingefügt hast
für diesen Key, eine leere Liste zurück
eine neue leere Liste
und genauso
für int, wenn du
ein DefaultDict
int hast, dann kannst du
jeden beliebigen Key abrufen und kriegst 0 zurück
Ja
Du kannst einen Counter
machen, das geht immer auf das
Ja, aber Counter gibt es auch
Da gibt es schon eine Klasse für, ja
Und die ist richtig cool, diese Counter-Klasse, die müssen wir uns auch gleich noch
Okay, wofür würde ich DefaultDict verwenden?
Das klassische
Beispiel ist, wenn man sich so ein Counter baut.
Aber nochmal, wenn du das gleiche, nochmal
auch, das gibt natürlich dann den neuen Wert zurück.
Genau, also wenn du einen Wert in
dieses DefaultDict
reinspeicherst, dann ist es wie ein normales Dictionary.
Also wenn es diesen Key schon gibt,
dann kriegst du das, was da gespeichert wurde. Das kann auch
was anderes sein als ein Int oder eine Liste.
Das heißt, es ist nicht eine Typisierung,
sondern es ist nur so dieser Fallback.
Da ist nochmal noch eine Zwischenfrage,
Kleiner Exkurs, wenn ich jetzt da ein Get mache auf so eine Liste, ja, auf so ein Default-Dict von der Liste
und ich habe dann eine leere Liste in der Hand und ich schreibe in die was rein.
Beim nächsten Mal auf denselben Key kippt ihr mir dann diese Liste, in der was drin ist.
Nee.
Oh.
Warum nicht?
Das wäre das, was Jochen vorher gesagt hätte, das wäre SetDefault.
Ah.
Weil du beim Abrufen entweder den Wert kriegst, der in der Liste, der in dem Dictionary drin ist,
oder den, den die Factory erzeugt.
aber der wird nicht automatisch in dieses
Dictionary abgelegt. Aber das ist doch
bei Listen, haben wir doch das Problem, dass dann das Objekt
der Liste dann es doch schon gibt und dass das
Objekt dieser Liste auf das dann ja... Genau, aber die wird nicht
in das Dictionary abgelegt.
Okay, das heißt, du musst die tatsächlich zuweisen.
Die du nur in der Hand hast und du musst die dann tatsächlich
zuweisen. Wenn du das möchtest,
dass du eine Liste abrufst und die dann bearbeiten kannst,
dann musst du SetDefault machen.
Und SetDefault heißt,
ruf einen Key ab, wenn es den schon gibt, gib mir
das, was da drin ist, ansonsten setze in dem
Dictionary den Wert, den ich dir da als Default angebe und gib ihn mir zurück.
Okay, ja das dachte ich, dass wir das was Default-Dictionary machen würde.
Okay, das heißt, dafür muss ich SetDefault machen.
Genau, dafür musst du das SetDefault machen.
Ja, aber die Funktion SetDefault, also sie ist in mehrerer Hinsicht verwirrend, sie ist
auch verwirrend benannt, wie man es auch gerade wieder sehen konnte.
Und vielleicht sollte man das echt, weil tatsächlich, wenn man so eine Default-Dict macht, ist es
sauberer.
Und ja, genau, was ich noch anmerken wollte zu den Factory-Funktionen, die man übergeben
muss.
also es kann eine Bedingung sein, die einzige
Bedingung ist, sie darf keine Argumente
nehmen. Genau.
Wenn man jetzt so mehrfach
verschachtelte Geschichten baut, das geht,
aber das wird dann auch relativ schnell
relativ unübersichtlich.
Ich habe noch
keine gute Lösung dafür, aber das ist,
das sieht dann komisch aus, aber
ja. Das ist ein bisschen blöd, dass es keine
Argumente sein können.
Also Factory-Striching-Manager gerne mal auf eine
bestimmte Art und Weise initialisieren.
Ja, das muss man ja irgendwie von einer
die Fraud-Tag schon wie alles schon erben und muss das
dann irgendwie schon hinstecken.
Ja, aber da gibt es etwas, also
zumal, wenn man jetzt bei unterschiedlichen
Keys unterschiedliche Sachen machen möchte,
das kann ja manchmal sein, du sagst so,
wenn ich diesen Key habe, okay, dann möchte ich ja gar keine
Liste dazu machen, sondern was ganz anderes oder so
und dann geht das
mit dem Default-Tag ja alles so nicht mehr so richtig,
eben deswegen, weil man kann halt nicht
Argumente angeben, was man dann, also
das geht da nicht mehr,
da gibt es aber auch etwas sehr Cooles, was ich auch erst
in der Vorbereitung. Ich habe ja einfach nochmal geguckt,
zu dieser Episode
habe ich mir nochmal so ein bisschen angeguckt, was habe ich denn an Literatur
zu Dicts? Steht da irgendwas Interessantes
drin? Da habe ich tatsächlich etwas gefunden, was ich noch nicht wusste,
wo ich auch sagen würde, oh cool, dass ich das jetzt
weiß. Und zwar gibt es
Dundamissing
als
sozusagen Spezialmethode,
die man überschreiten kann, wo man
dann den Key bekommt. Das ist quasi der Key Error.
Du kannst den Key Error überschreiben.
Ich mache dann DefaultDict,
mache ich dann eine neue Klasse, die von DefaultDict erbt und überschreibt
dann dann dann Missing und guckt dann mit einem Match-Case-Statement, was da drin ist.
Genau, oder du kannst von Default-Ticket erben, na klar, aber
das musst du dann ja im Grunde nicht mehr, weil wenn du die Methode überschreibst, dann bestimmst du ja selber, was passiert.
Und da kannst du alles machen. Das ging früher übrigens auch nicht.
Ich konnte früher nicht von Dict erben, deshalb gibt es noch eine Klasse, die UserDict heißt.
Achso, das heißt dann, ich mache tatsächlich sowas ähnliches wie UserDict und ich mache
eine neue Klasse auf die erbt einfach von Dict und da überschreibe ich dann nur die Missing-Methode und dann gucke ich halt,
statt dem Key-Error rauszugeben,
dass er dann tatsächlich irgendwas Neues anstellt.
Das würde auch tatsächlich funktionieren, aber
diese Diskussion hatten wir
in dem Python User Group
Düsseldorf Channel auch
vor kurzem, ob es denn okay ist
von Dict zu erben oder wenn man lieber von UserDict
erben soll oder so. Und ich hatte das halt noch
so im Hinterkopf, dass man von UserDict erben soll
und nicht von Dict. Und
tatsächlich habe ich jetzt auch
nochmal nachgeguckt und nee, man soll
von UserDict erben und nicht von Dict.
Also man kann das ja zwar jetzt, aber
Was ist da der Unterschied?
Der entscheidende Unterschied, warum das
unter Umständen einem Probleme machen kann,
ist, dass
bestimmte
Methoden, also Missing
ist jetzt, die funktioniert, die kann man überschreiben,
aber bestimmte andere nicht. Und wenn du dann
auch bestimmte andere Arten,
wenn du da Sachen mitmachst, dann
geht das an den Methoden, die du überschrieben hast,
vorbei. Das heißt, wenn du
von dem Bild entdeckt hast,
und dann überschreibst
halt irgendeine Methode und denkst, ja, müsste doch funktionieren,
dann funktioniert es manchmal halt vielleicht nicht,
weil zum Beispiel, also auch der Konstruktor
davon ist halt so, der schreibt das halt
irgendwie direkt, der geht nicht über die
Set-Item, Get-Item-Geschichten,
die es da halt normalerweise gibt. Das heißt,
dann verhält sich das Ding unter Umständen
unerwartet. Und ja, Laufzeitverhalten
ist auch so ein bisschen anders.
Und, das habe ich jetzt aber auch
wieder vergessen, also es war auch irgendwie, ist eine
wichtige Geschichte, warum das, wenn das
ein Data-Attribut ist und sozusagen die Zugriffe
daher nur delegiert werden.
Das macht auch irgendwie, ich glaube, es kann sogar sein, dass
das der Grund ist, weshalb man SetItem, GetItem
dann überhaupt quasi richtig überschreiben
kann, weil wenn das halt...
Weil es delegiert wird. Ja, genau, genau.
Und daher sollte
man, wenn man das selber, wenn man
erben will und will Sachen überschreiben, dann
lieber UserDict nehmen, statt einfach
von Build enternen. Also UserDict
ist quasi
eine Klasse, die das gleiche Interface hat wie
Dictionary, aber
eben ein Attribut heißt, das heißt
Data
und das ist ein Dictionary und einfach alles
durchrecht an dieses Data.
Und das bedeutet, dass wenn ich von UserDict
ableite, kann ich jede beliebige Methode
überschreiben und die wird dann auch korrekt
aufgerufen, auch Konstruktor und alles mögliche.
Ja, genau.
Ja.
Ja, okay, wusste ich auch nicht. Ich wusste nicht, dass es so Unterschiede gibt.
Ja, es ist immer wieder interessant, auch wenn ich dachte,
also ich meine, das verwendet man ja jeden Tag
und irgendwie schon lange und so und dann ist es so,
kann ja eigentlich nichts Neues mehr.
Aber manchmal so, ja.
Aber das ist was, was man doch relativ selten macht von Dictionary.
Also generell,
Bild-Ins, so Sachen,
fühlt sich immer so ein bisschen komisch an.
Ja, ist nicht so häufig.
Die sind einfach gut genug.
Beziehungsweise, wenn man
eine neue Datastruktur sich schreibt,
dann benutzt man normalerweise eben eine
und leitet nicht direkt
davon ab. So ist meine Erfahrung.
Instanziert die dann irgendwie so mit so einem
Invektor-Pattern oder sowas, dass man die halt dann benutzt?
Genau, dieses Data, dass du halt
und sagt, okay, mein Baum ist eigentlich eine Liste, aber ich habe eine Liste, die das macht.
Ich habe nicht das Interface von Liste geerbt, sondern ich habe halt eine in der Hand, die das macht.
Das ist so meine Erfahrung. Ich weiß nicht, wie ihr das seht.
Doch, doch. Ich sehe das ganz genauso.
Achso, das ist auch noch der eine Grund dafür, warum das mit dem Delegieren eine gute Idee ist,
und Jochen unterhalten sich die Programmiersprache Python Also in einem Kontext wo man sich dann fragt wie man so Dia macht auf dein Objekt und dann sieht man halt einen ganzen Haufen komisches Zeug wo man sich dann so h warum ist das denn alles da drin was man halt einfach so mitbekommt wenn man das wenn man
da direkt erbt.
Also, ja.
Okay, ich frage mich alles.
Wir müssen noch so ein paar Sachen, ich habe jetzt meine
Notizenliste ist leider gerade leer gegangen,
aber
da ist so ein Ladegerät und da ist
ein, das kann man, das kannst du am Telefon anschließen.
Oh, du hast USB-C? Wow.
als Apple-Haushalt USB-C.
Ja, ja, brauchen wir das schon.
Cool.
Es gibt eine Methode in Dictionary,
wo wir gerade über das Dictionary-Interface
sprechen, die ist in 3.9 dazugekommen.
Es gibt eine, in 3.9 hat sich
das Dictionary-Interface verändert.
Und zwar ist der
Pipe-Operator dazugekommen.
Ah, ja, richtig.
Ja, natürlich.
Und das ist sowas, was,
wenn man das braucht, dann ist das
ungeheuer wichtig und wenn man es
nicht braucht, dann ist es so.
Okay, nie gedacht, dass jemand sowas brauchen könnte.
Das ist Dictionary-Vereinigung.
Ja, Unions zwischen von Dicts.
Genau, da gibt es jetzt den Operator dafür.
Früher musste man immer,
jede von uns hat so eine Sammlung von Tricks,
wie man Dictionaries vereinigt.
Ja, das ist ganz einfach mit Stern, Stern
und unter Dictionary und
ja,
und das gibt es jetzt als Operator und auch mit
Pipe gleich, also man kann auch gleich rein
vereinigen, wobei das einfach ein Update
ist meiner Meinung nach, oder?
Oh, das würde ich jetzt ausprobieren, das weiß ich auch nicht, aber es stimmt, ich wusste, dass das passiert ist, ich habe es aber nie verwendet,
seitdem, daher ist es mir jetzt gar nicht mehr bewusst.
Moment, ein Update ist ja Union, ist das exklusiv, ist die Frage, ne?
Es ist immer exklusiv, weil du ja keine Keys verdoppelst.
Ja, aber dann geht das nicht mit dem Update, weil bei Update werden ja nur die Keys geupdatet, die in dem Update enthalten sind.
Nee, ein Punkt Update, ein dictionary.update übernimmt alle Keys und Values aus dem...
dem Eingegebenen. Das überschreibt
alles, was da drin ist. Genau, aber wenn welche
vorher schon drin waren und die dann überschrieben werden,
aber wenn die vorher schon drin wären, die nicht,
nein, aber wenn die vorher schon drin waren
und nicht in dem neuen drin sind, dann sind
die, wie sie vorher waren. Aber wenn du den
Union Operator gleich machst, dann sind sie eben
nicht mehr drin,
weil sie halt nicht in dem Update sind.
Das verstehe ich jetzt nicht.
Okay, du hast zwei einigermaßen
Distributiven. Du hast D1 und D2.
Genau, du hast zwei einigermaßen Distributiven.
Und das sind irgendwie zwei Keys gleich.
Wenn du jetzt mit dem Update machst,
werden die zwei gleichen Keys
in dem ersten Dictionary überschrieben.
Wenn du das, ne, erstes Update,
wenn du aber die
Union machst,
nein, dann sind nur noch die zwei Keys drin.
Nee, das kann ich.
Nee, das wäre ja der
Schnitt nicht zu beantworten.
Achso, stimmt.
Das gibt es nicht. Das gibt es nur bei Set.
Gibt es nicht auf den Schnitt? Das gibt es nur bei Set.
Bei Set gibt es das.
Das ist aber...
Gibt es nicht auch die Intersect?
Z.Intersect. Ne, für Dictionaries gibt es kein Intersect.
Okay, schade eigentlich.
Weil das wäre doch eigentlich sehr logisch, dass das mit dem...
Siehst du, jetzt habe ich den Piper-Properator nicht richtig verstanden.
Es wäre logisch, dass es diese ganzen mathematischen
Operationen alle für Z und Dictionaries haben.
Genau, dass du halt quasi dann nicht nur sagst, du machst halt
einfach irgendwie ein und und oder wie auch immer man das machen will
von dem anderen Dikt und dann hast du die Unions direkt.
Das wäre doch schön syntaxisch.
Ich probiere das mal in der Rappel aus.
Ja, mach mal. Union ist oder
und das ist
einfach die Vereinigung.
so die Keys aus dem einen Dictionary und die Keys aus dem anderen Dictionary.
Ja, okay.
Mit den Werten aus dem jeweils letzten.
Mach mal und und.
Nee, das geht in der, nee, und und geht schon mal gar nicht.
Und und gibt es in Python sowieso nicht?
Gibt es nicht.
Aber und und geht nicht.
Und dann sagt er unsupported operand.
Bit twice geht auch nicht.
Ja, okay.
Also tatsächlich, es geht nur die Vereinigung, ja.
Ja, okay.
Dann ist das gleich wie ein Update.
Wohingegen bei set, wenn man das jetzt so macht.
Bei set gibt es intersect.
Es gibt set.intersect.
Es gibt z.union und es gibt z.
und es gibt z.
Es gibt noch eine dritte, difference.
Symmetric difference oder sowas.
Ja, genau.
Symmetric difference ist ja das eine
plus das andere minus das eine.
Schade, dass ihr Interfekt nicht habt.
Warum hat der das denn nicht? Also bei selben, das bei set geht,
aber bei dix nicht. Das müsste ja irgendwann mal reinkommen.
Die Frage ist, wie sollen denn dann die Values
aussehen?
Bei der Intersection der Keys.
Welche nimmst du denn dann?
Hm.
Jetzt hast du mich.
Eine Liste von beiden wahrscheinlich.
Ja, aber das wäre dann schon sehr unerwartet, oder?
Ich meine, man könnte auch auf die Idee kommen,
es müsste anders sein und dann wundert man sich halt,
was passiert ist.
Also eigentlich müsstest du
den Schnitt über die Keys machen
und dann entscheiden, aus welcher
Quelle du die Value nimmst.
Das ist halt quasi wie beim Update
mit Exclude oder sowas.
Kann man das machen mit Exclude?
Nee.
Auch doof.
Ja, also was mir jetzt wieder anfällt,
es ist irgendwie relativ ähnlich zu dem, was man irgendwie
bei den neuen Sachen hat, wie mit Data Classes oder
PyDentic oder sowas oder
was gibt es denn noch, alles Ethos oder sowas?
Also was diese, ja,
oh, das gibt es auch noch, ja,
Named Tuple. Ja, genau, Named Tuple.
Genau, das ist auch spannend. Warum denn
Named Tuple?
Ja, das ist ein total komischer
Name dafür. Ich weiß auch nicht.
Um dot notated Zugriffe auf
irgendwelche Objekte zu haben für die einzelnen.
Okay, aber dann, also
Was ist denn der Unterschied zwischen einem Dictionary und einer Klasse?
Weil bei einer Klasse habe ich auch Namen drin, Punkt irgendwas und da ist genau ein Wert dazu drin.
Du hast einen Konstruktor und irgendwie noch...
Ja gut, aber das ist ja...
Der Konstruktor ist nur eine Konvention.
Du kannst auch deine Sachen anders konstruieren, genau.
Also ich würde sagen, es gibt keinen großen Unterschied.
Tatsächlich ist es eine sehr ähnliche Geschichte und ich glaube, es ist ja auch so...
Alles die Interpretierung ist tatsächlich auch so.
Genau, also in Python-Objekte, das sind halt Dicts, was ihre Struktur angeht.
Mit ein kleines bisschen Syntax dazu.
Genau.
Tatsächlich ist es sogar, also ich weiß nicht, ob das bekannt ist, unter uns dreien sicherlich, aber unter den Hörern vielleicht nicht.
Jede Instanz einer Klasse ist im Wesentlichen ein Dictionary.
Also das hat ein Attribut, das heißt unterstrich, unterstrich, Dict, unterstrich, unterstrich.
und da stehen die Dinge drin, die
die Values in dieser Instanz sind.
Also eine Instanz ist immer ein Dictionary
in Python.
Das ist irgendwie
komisch oder seltsam.
Gerade wenn man von anderen Programmiersprachen
kommt, weil in anderen Programmiersprachen ist es ja nicht so.
Weiß ich nicht. Also ich würde gerade
sagen, bei dem, was üblicherweise
so als Skriptsprache
qualifiziert wird,
da ist das auch, also bei JavaScript,
da heißen die Dinger sogar Object.
Vielleicht ist das das entscheidende Merkmal
in der Skriptsprache
Also bei
oder bei Perl war das auf jeden Fall auch so
da waren auch, also ich meine
das hat ja keine offizielle
Bei dynamischen Klassen und dynamischen Instanzen geht es ja
quasi nicht anders, du musst ja quasi diese Zuordnung
haben von Attributname zu
irgendeinem Wert
Bei kompilierten Sprachen ist das ja anders
Ne, da ist es anders, genau
Bei kompilierten Sprachen musst du es nur während der Kompilierungszeit machen
und dann kannst du sagen, okay, das Attribut
mit dem Namen x ist halt Feld Nummer 2.
Ja. Man kann das in Python
auch machen, quasi. Man kann das halt
festdengeln, ohne dass das halt dann
noch so dynamisch...
Ja, man kann halt die Attribute
in einem Spezialattribut
Thunder Slots angeben und dann
sind die halt da fix.
Die kann man dann aber auch nicht mehr dynamisch zuweisen.
Das ist aber auch nur
Konvention, oder? Ne, ne, das ist dann tatsächlich
schneller.
Wenn ich ein Slot-Tick mache, dann kann ich das trotzdem
zusätzlich machen.
nochmal dann sein Slot.
Achso, Moment, kann ich dann trotzdem
dynamisch zuweisen? Ich weiß es nicht, meine, das geht dann nicht mehr.
Das muss ich ausprobieren.
Jochen macht seinen Editor an.
Einer von uns beide ist gleich falsch.
Oder eben NameTupel. NameTupel ist
genauso, nur halt
schneller.
Weil der eben diesen Aufruf nicht über ein Dictionary macht,
sondern über eine lineare Liste, weil die Annahme ist,
dass du nicht so viele
davon hast. Oder vielleicht
ist das so eine Hybrid-Sache.
So ein bisschen ist das Dictionary ja der Kern von Python.
Es gibt ja so eine Liste...
Moment, ich habe es gerade ausprobiert.
Nein, wenn man halt Slots definiert hat
und dann was anderes dynamisch zuweisen möchte,
kriegt man Exception, Attribute, Error.
Also wenn man Slots macht, dann ist es kein
richtiges Dictionary, sondern nur...
Also es ist halt auch so ein Trick, damit kann man halt, wenn man viele
Objekte hat oder so, damit kann man die Objekte selber
schneller machen und sie brauchen viel weniger Speicher.
Jetzt muss man noch erklären.
Aber Nailtubel macht das genauso, oder Jochen?
jetzt ist auch schneller als
eine allgemeine Klasse.
Ja, ja, klar. Name-Tupel macht das genauso
und darüber funktioniert, ich glaube,
dann intern kann es sogar sein, dass die interne Datenstruktur
Tupel ist und sich dann sozusagen
nur eine Zuordnung gemerkt wird von
Index auf irgendeinen Namen.
Aber das würde ja schon nichts bringen,
sondern das würde ja dann Hashtag den gleichen
aufrufen, sondern das muss eine andere Struktur
sein, das ist keine Hashmap.
Ja, ja, ja, nee, das ist irgendwas anderes, keine Ahnung.
Was auch immer.
Man darf nicht vergessen, wenn ich eine kleine
Menge an
Keys hat, dann ist
so eine Art Listenzuweisung, also ich
merke mir einfach, die Keys
in einer Liste und gehe die Liste linear durch,
das kann schneller sein als
so ein Hashmap-Zugriff.
Für kleine Werte von n.
Für kleine Werte von n ist o von n
kleiner als o von 1. Kann sein.
Kann gut sein, ja. Und
das ist, glaube ich, der Trick von Slots und der Trick von Name-Tupel,
dass die halt sagen, okay, wir
machen keine allgemeine Zuweisung, sondern wir
sagen, aha, wir haben ja nur drei
benannte Attribute, dann ist es besser, die in einer Liste zu haben.
Okay,
Slots bitte noch einmal explizit erklären,
weil das kommt gerade zum ersten Mal vor.
Slots und Name-Tupel.
Wie gesagt,
darüber weiß ich jetzt gar nicht.
Ich dachte, wir machen was.
Erklär es mal als Name-Tupel.
Was ist denn ein Name-Tupel?
Ich wollte gerade nach Slots fragen.
Ja, das kommt gleich.
Naja, da definierst du sozusagen
ein Objekt dadurch, dass du am Anfang
Du gehst also, glaube ich, wie ist der Aufruf?
Name-Truppel, dann sagt man irgendwie
einen Namen dafür und dann sagt man die
Attribute, die das haben kann
und dann
Und das verhält sich dann aber wie eine Klasse. Ja, genau.
Und dann kann man mit Punkt drauf zugreifen.
Aber nur mit diesen, die ich da angegeben habe.
Also wenn ich ein Name-Truppel habe, das heißt
Fuba
Keine Ahnung, das heißt Fuba und das hat die Attribute
A, B und C
Dann kann ich ein Fuba.a
machen und Fuba.b und Fuba.c
und kriege die entsprechenden, das verhält sich
dann wie ein Dictionary für diese drei
Keys. Aber Dict kann ich ja nicht mit
Dot machen, muss ja mit den Key-Ketten. Genau.
Also das ist wie eine Klasse.
Also das ist so
ein Ding, das mache ich häufig, dass ich
einfach eine Klasse mache, die heißt DataHolder
und die hat keine Attribute,
weil dann kann ich nämlich mit Punkt irgendwas.
Wenn wir jetzt gerade schon bei NamedTouples noch sind, da gibt es übrigens
auch eine kleine Neuerung, weil früher gab es ja immer vom Collections
NamedTouple, man musste NamedTouple off machen und
jetzt gibt es aber auch das Typing NamedTouple und Typing
NamedTouple ist nur ein bisschen eleganter, weil dann kannst du einfach
das wie eine Klasse schreiben.
und darunter die Attribute.
Ich würde NameTupel gar nicht so
prominent, weil auch das
ist, glaube ich, nicht mehr so wirklich
empfohlen und nicht mehr so richtig aktuell.
Das gibt es halt noch.
Aber eigentlich, was man
darunter stellt...
Wenn man NameTupel verstanden hat,
dann ist Slots leicht zu erklären, weil Slots ist
nämlich eine andere Syntax für die
gleiche Funktionalität.
Du sagst, welche
Attribute eine Klasse haben darf und
dann hat es nur genau diese Attribute.
Das heißt, okay, also in Slots ist eine Dann-Dann-Methode,
die in einer Klasse drinstehen kann.
Nicht eine Methode, nein, nein, das ist ein Attribut.
Das ist ein Attribut, ah, okay, das ist ein Attribut.
Und das ist eine Liste von Namen rein.
Und das ist eine Liste und in der Liste stehen quasi
die Strings drin von den
Namen, die als Attribut
einer Klasse, die als Methode oder Attribut
erlaubt sind.
In unserem Beispiel von eben wäre dann die Klasse, die Klasse hieße Fuba
und die hätte ein Attribut, das hieße Dann-Dann-Slots
und da steht drin A, B und C
als Strings. Stehen da auch
Methodennamen drin oder nur
Attributnamen.
Nur die Attributnamen.
Und wenn ich da Methodennamen reinschreibe, dann kann ich da eine Methode für definieren,
die trotzdem funktioniert?
Kannst du machen, klar, wenn du willst.
Da müsste man ja ausprobieren, was da passieren kann.
Das kannst du generell machen.
Du kannst generell an jede Klasseninstanz
eine Methode dran machen, die muss halt
den Parameter self haben.
Als erstes. Und dann funktioniert das wie die Methode.
Weil Methoden an Klassen sind nichts anderes
als
Funktionen, die den Parameter self haben.
Aber was ist denn, wenn das nicht in den Stops drinsteht?
Ja, wenn es nicht in den Slots drinsteht, kannst du nicht darauf zugreifen.
Genau, das heißt, die Methode kann ich nicht aufrufen, weil es nicht in den Slots drinsteht.
Das heißt, auch die Slots sind für Methoden dann exklusiv.
Du kannst die Methode in die Klassendefinition reinschreiben und die kommt dann zusätzlich zu den Slots dazu.
Du kannst sie halt nicht dynamisch hinzufügen.
Du kannst sie nicht dynamisch hinzufügen.
A-Slots wird zusammengebaut aus dem, was in dem Attributslot drinsteht und in den Namen, die als die Methode dienen.
Da wäre ich mir nicht so sicher.
Probier es mal auszuhochen.
Ja, ist meiner Meinung nach so.
Jetzt müssen wir gerade ein bisschen tippen.
und wir gucken, ob wir die solche haben.
Okay.
Also foo.astl.
Das funktioniert schon mal.
Also genau so.
Und jetzt sagen wir foo.slots.
Ich glaube nicht, dass das zusammengebaut wird.
Ich glaube, dass slots bleibt so, wie es ist.
Aber das funktioniert. Methoden gehen, ohne dass
ein Slots drin steht und es ist nicht ein Slots drin.
Du kannst aber Methoden hinzufügen.
Weil die Methoden
an dem Typ dranhängen und nicht
in der Instanz.
Das heißt, an einer
Instanz, die ein Slots-Attribut hat,
kannst du nichts verändern. Du hast nur genau
diese Keys, die da drin sind.
In dem darüberliegenden
Typ hast du Methoden drin und da kannst du
auch, kannst du alles mögliche drin haben. Das ist deine
normale Klasse. Okay, es geht leider nur für die Instanz,
die Slots. Genau.
Die Slots sind für Instanzen von dieser Klasse
und wenn diese Klasse aber selbst
noch Methoden hat oder Attribute, ja, du kannst
auch in diese Klasse ein Attribut reinschreiben. Du kannst da x gleich
10 reinschreiben und das kannst du auch auslesen
und du kannst es auch an der Klasse
verändern. Ja, okay.
aber nicht in den Instanzen.
Weil in den Instanzen darfst du nur auf Slots zugreifen.
Ja.
Und das bedeutet, dass
eine Klasse mit Slots im Wesentlichen
wie ein Name-Tupel ist, nur besser.
Mit besserer Syntax und
mehr Methoden. Und das ist auch
der Grund, warum Name-Tupel nicht mehr so richtig...
Jawohl, aber ich finde, dass das neue Name-Tupel von
Typing ist doch gar nicht so schlecht.
Nee, also es hat auch noch andere Nachteile.
Es gibt ja jetzt auch
etwas, was man vielleicht eher
nehmen... Also vielleicht meinst du es so,
Es gibt ja Dataclasses, die sind ja auch jetzt in der Sprache drin.
Ja, genau.
Und die sind auch in eigentlichen, also es gab es auch, ich weiß nicht, Artikel dazu.
Ich meine, ich habe es jetzt nur mal so gelesen, ich habe es nicht wirklich selber überprüft,
aber so, wo Leute sagen, also bitte nehmt doch alle Dataclasses und nicht mehr nehmt Tuppel,
weil Dataclasses ist schneller, ist besser, ist in jeder Hinsicht besser.
Es gibt keinen Grund mehr dafür.
Das alte Zeug ist nur noch drin.
Man kann es lesen.
Ja.
Okay, ja.
Es kann mehr und es ist schneller.
Also ich meine, es gibt keine großen Nachteile.
und es gibt das natürlich, also
das Vorbild für
Dataclass ist halt dieses
Atris-Modul, das sehr beliebt ist.
Das kann halt dann noch viel mehr.
Und ist auch relativ schnell, wenn ich das richtig verstehe.
Ist auch sehr nett, ja.
Und also das ist
was vielleicht damit angefangen hat, dann Dataclass
ist eingebaut und jetzt gibt es halt auch noch sowas wie
Pydentic, das ist ja auch so ähnlich.
Das ist noch schneller.
Der Münster bei Dataclass ist nicht schneller als Atris.
Ich weiß nicht, ne, Pydentic meine ich auch
eine eigene Geschichte. Ja, bei Denny ist es eigen, aber es ist nicht da.
Doch, doch.
Nee, ist es nicht? Nee.
Es ist ein Einstehen sogar langsamer als Etos zum Beispiel.
Okay. Jochen dachte, es wäre schneller.
Ich dachte, es wäre Data-Klari-Grunden drin.
Ich habe irgendwo so ein Video, das muss ich eigentlich mal in den
Schirm losverdenken, wo jemand das ganz gut auseinander nimmt,
wo der so im Timing-Stop... Also, das muss
sich mal irgendjemand ganz genau angucken und
Bescheid sagen, wie das denn wirklich ist.
Und dann in der Episode hier in den
Podcast kommen und uns das allen erklären, wie es ist.
Genau, das wäre gut.
Ja, absolut.
Genau, aber es ist auf jeden Fall ein Ding,
was halt, und
diese ganzen Dinge, wenn man
die sich alle anguckt, also NameTouple
ist halt das, was man am wenigsten nehmen sollte von den ganzen
Sachen.
Ich finde ja die moderne Sondergeschichte, das sieht eigentlich ganz hübsch aus.
Das ist halt so schnell.
Wenn du es halt aufschreiben willst,
vom Typing-Import NameTouple, dann machst du einfach
auf, keine Ahnung, NameTouple
define NameTouple und irgendwas und dann
schreibst du halt die Attribute untereinander wie in der Klasse,
definierst. Dir ist klar, welchen Datentyp haben die denn
und so. Das sieht schon so aus als...
Okay, vielleicht muss ich mir das auch nochmal angucken, weil
das ich das vom Typing importiere, kenne ich jetzt noch
gar nicht. Ja, aber das ist auf jeden Fall, glaube ich,
ich weiß auch gar nicht, ob sich eine Implementierung da was geändert hat,
aber ich glaube, wir werden es eigentlich haben, oder?
Also das musst du erstmal kurz aufmachen,
um dir das mal anzuschauen.
Okay, dann muss ich da mal eingehen.
Ich würde tatsächlich eher Dataclasses verwenden für diesen
Newscase, aber
ich habe ja immer seltsame Ansichten.
Ja, das ist eine neue Sache.
Abgefunden, dass ich nicht im Standard bin.
Ach, so sieht das...
Nee, okay.
Ach doch, so sieht das aus, ja, okay.
Ja, typing.namet-tuppel
und dann sagt man hier irgendwie...
Ja, aber das ist sogar noch...
Moment, jetzt muss ich mal...
Ja, da unten, also das nächste Beispiel...
Wir wissen, dass die Zuhörer den Monitor nicht sehen können.
Genau, das ist das Problem bei Podcasts.
Und das Problem ist auch, ich kann das jetzt nicht vorlesen,
kann ich schon, hilft nur nicht.
Ja, genau, aber ich finde so die Gesundheit,
das sieht doch gar nicht so schlecht aus.
Ja, okay, also gut.
und muss ich das mal jemandem anklicken
und dann muss ich es halt sagen.
Also es ist auch eine Möglichkeit, die man machen kann.
Ja, ja, ja.
Ja.
Ja, ja.
Okay, aber das ist ja nur syntaktischer Zucker, oder?
Ja, syntaktisch Zucker.
Sehr gut.
Also dann ist es quasi Name-Double.
Okay, schön. Das ist auch okay.
Es gibt noch zwei Dinge, die ich
vorhin gelernt habe. Das erste ist Counter.
Wir haben es schon kurz angesprochen.
Counter ist auch eine Dictionary-Subklasse.
und die macht im Wesentlichen das, was sie sagt.
Ich gebe eine Sequenz rein und die zählt, wie oft jedes Element drin vorkommt.
Das heißt, wenn ich einen String reingebe, dann habe ich hinterher ein Dictionary
und in dem Dictionary steht drin, wie oft jeder Buchstabe in diesem String vorkommt.
Und das ist großartig, weil das baut man sich so oft selbst
und das baut man sich so oft von Hand und macht ein Default-Dict oder macht ein Get
und inkrementiert die Zahl dann und so weiter.
einfach einen Counter und die Sequenz
reintun und fertig. Und man kriegt einen Dickschneider
raus mit der Anzahl.
Super, ist großartig. Und das hat auch diese ganzen
Funktionen, die man dazu braucht. Also wenn man das dann
updaten möchte oder wenn man das
wenn man
einen Generator hat oder wenn man
irgendwas anderes in der Hand hat und das nicht genau
vorher weiß oder wenn man zwischendurch noch was machen möchte,
ist großartig. Ein Counter
zusammen mit einer Comprehension, super.
Ja, ja.
Es deckt so viele von diesen Fällen ab, für die man
sonst Default-Dict verwendet.
Ich habe noch was anderes schönes gefunden
und zwar heißt es Chainmap
Das ist auch ein Corrections-Modul drin
Was ist denn eine Chainmap?
Eine Chainmap
das ist so ein
Ich hatte so ein bisschen an JavaScript Objects erinnert
Wenn du
nach einem Key suchst
dann suchst du quasi durch die ganze
Reihe durch. Das heißt Chainmap nimmt eine
Menge von Dictionaries
und wenn du nach einem Key fragst
dann guckt er im ersten
Dictionary, ist der da drin? Wenn er da drin ist, kriegst du den Wert. Wenn er nicht drin ist,
guckt er im zweiten nach. Wenn er da drin ist, kriegst du den Wert. Wenn er nicht drin ist, guckt er im dritten
nach und so weiter, bis er alle seine darunterliegenden Dictionaries
durchgeschaut hat. Wenn er es nirgendwo findet, kriegst du immer noch einen Key Error.
Wenn du aber einen Wert reinschreibst,
in diese Chain Map, dann schreibt er das immer in das oberste
Dictionary rein. Das heißt, du veränderst nur das erste Dictionary aus deiner Kette,
hast aber lesenden Zugriff
auf die darunterliegenden.
Und das ist so ein bisschen
so wie Objekte in JavaScript
funktionieren, wie Object in JavaScript funktioniert.
Wenn du liest, liest du immer
aus dem Ersten, was verfügbar ist,
aber wenn du schreibst, schreibst du immer ins Oberste rein.
Ja, ja, ja.
Ja, ich überlege gerade auch, also ich meine,
das ist auch sowas, ja, ich weiß es nicht genau,
aber ich mache jetzt auch so ein bisschen
JavaScript gerade und
und was dann doch ein bisschen einfacher hinzuschreiben ist als in Python,
ist halt diese 3-Punkt-Spratch-Operator-Syntax,
wo man sich neue Sachen generiert, indem man ein altes Ding nimmt
und dann sagt man Punkt, Punkt, Punkt, altes Ding
und dann schreibt man noch ein neues Ding dazu oder so.
Und mit Chainmap hat man ja da quasi was ganz Ähnliches.
Das ist eben, wie gesagt, diese Prototypsache.
JavaScript ist halt der Kern von JavaScript.
jedes
Object oder jedes Dictionary in JavaScript
hat einen Prototypen, auf den
du zurückfallen kannst und das kannst
du hier mit Chainmap nachbauen.
Ja, nett.
Fand ich sehr schön, dass es gibt.
Habe ich noch nie gebraucht.
Wüsste jetzt auch nicht, an welcher Stelle ich das
einsetzen würde, aber
gibt es auf jeden Fall.
Ich glaube, wenn man das braucht, ist das eine sehr
sehr nützliche Sache.
und
weil man so Hierarchien damit bauen kann.
Ja.
Vielleicht noch einmal ganz kurz, weil ich gerade nachgeguckt
hatte zu diesem, which Python
Data Classes best, habe ich ein Artikel,
also ein Video gefunden von einem Kanal
M-Coding heißt und
da vergleicht jemand tatsächlich
Data Classes, NameTupil, Tupil
Etters und Pydentic
nach Geschwindigkeit und
Memory Efforts und so und da scheint
Pidentik vor allem beim Erstellen von den Objekten relativ schlecht ab.
Okay, gut, ja.
Das irgendwie 15 Mal so lange dauert oder so.
Aber sonst vielleicht schnell.
Ja, gut.
Im Laufe seines Programmiererlebens hat er sich davon weg entfernt.
Aber Geschwindigkeit.
Er hat den Notizzettel wieder angemacht.
Ja, genau, Geschwindigkeit, ja.
Da ist die Frage, braucht man das überhaupt, will man das?
Genau.
Haben wir nicht genug Hauptspeicher?
Das war von anderen Bereichen.
Nie genügend Geschwindigkeit und nie genügend.
und kommt darauf an.
Letztens jemand,
den kennt ihr bestimmt auch,
Pavel Mayer
aus
Chaos Radio
oder
aus dem Chaosumfeld, ne, die kenne ich aber nicht.
Ah, okay, der, naja, gut.
Der hatte das mal
irgendwie so beschrieben, dass ein Computer
eigentlich für ihn nur eine relevante Eigenschaft,
also ein
Attribut hat, das irgendwie wichtig ist
oder das drei gibt,
und die Programmiersprache Python.
in denen das wichtig ist,
die Geschwindigkeit und Geschwindigkeit ist immer irgendwie
so ein Faktor, der wichtig
ist, aber man kann
da so tief reingehen, wie man
möchte und es gibt immer noch jemanden, der das schneller macht.
Ich sehe mir
sehr gerne die Videos von Casey Muratori an
und der kommt halt aus der Spieleentwicklung
und der sagt,
man kann den C alles machen, also solltest
du den C auch alles machen, aber wenn es schnell
sein muss, dann musst du halt schon auf die Intrinsics
gehen und den Prozessor kennen, den du da
gerade benutzt und dann
den Befehlssatz
kennen, weil dann kannst du nämlich alles
256 Mal so schnell machen wie vorher.
Ja,
das ist prinzipiell
korrekt.
Vielleicht ist SMB-Coden auch zu langsam,
also wenn man es gut kann, ich weiß nicht.
Man kann es sicherlich gut genug,
aber...
Noch kurz zu...
Da gibt es auch gerade auf Netflix so eine
Miniserie oder so,
The Billion Dollar Code, die ist quasi mehr so,
und orientiert sich an
deren Biografien.
Und die scheint wohl ganz gut.
Wir machen wieder Werbung, Jochen,
das ist aber eine werbungsvolle Folge.
Diesmal ist ja noch gar nicht so...
Gut, wir machen Werbung,
Werbung machen wir immer, aber wir werden nicht dafür bezahlt.
Netflix,
falls ihr zuhört, der Jochen wäre
durchaus offen dafür, bezahlt zu werden.
Also Johannes Verkunde ist ja nicht mit
anderen Werbepartnern direkt parallel...
Also Netflix-Termin würde ich vielleicht auch schenken.
Also wir hatten ja letztes Mal,
also wenn wir jetzt schon das Thema Werbung haben,
ich mache mal eine Chapter Mark hier.
Ja, wir haben ja
überlegt, ob wir Werbung mal schalten sollen
und ein bisschen uns darüber lustig gemacht und wir haben ein bisschen
Feedback bekommen, wo wir sagen, ja, mach doch einfach.
Ja, dann haben wir jetzt auch gedacht, ja, okay.
Na gut, dann machen wir halt.
So ein bisschen kostendeckend arbeiten.
Gibt es Leute, die euch bezahlen?
Das ist ja verrückt.
Aber berührt und schockiert.
Du wirst nicht bezahlt.
und das macht ja gar keiner.
Achso, ja gut dann.
Ja, nicht so direkt,
aber ich meine, das wäre natürlich so eine Sache, die man machen könnte.
Man könnte also einmal Hosting
kosten und so die Anfälle ein bisschen damit vielleicht
bezahlen.
Aber was man auch machen könnte, wir könnten
dem Johannes ordentliches Audio-Equipment
schicken zum Beispiel.
Ja, da müssen wir nochmal drüber nachdenken.
Dann ist das jetzt hiermit der Spendenaufruf.
Wenn die Zuhörer gerne möchten, dass ihr mich besser hören könnt,
dann folgen wir
mit Bitcoin-Adresse.
Wir schalten ab jetzt einfach Werbung.
Aber wenn ihr dann Werbung schalten würdet
und dann auch Geld einnehmen würdet,
dann könntet ihr euch ja auch richtige Gäste leisten.
Wir haben keine richtigen Gäste.
Ich wäre dann einfach gar nicht mehr hier.
Vielleicht könnte man sich dann auch andere Hosts leisten,
die das so etwas professioneller machen
und sowieso eine andere Webseite,
die auch nicht so schnacker aussieht.
Was könnten wir denn dann eigentlich machen?
Dann könnten wir uns ein Strand kaufen.
zur Ruhe setzen und mal eure Hobbys verfolgen.
Vielleicht, keine Ahnung.
Vielleicht machen wir einen Podcast auf.
Ja.
Naja.
Ich warte immer noch auf mein Schloss Ja M du auch noch einen Spendenaufruf starten Also mein Spendenaufruf war f ein gescheites Mikrofon Dominiks Spendenaufruf ist f ein Schloss
Ja, für mein, nicht für ein Schloss,
für mein Schloss.
Ja, ja, für sein Schloss.
In diesen ganzen anderthalb Stunden,
wo wir jetzt schon zusammensitzen,
haben wir jetzt tatsächlich noch gar nicht drüber gesprochen,
was ein Hashmap überhaupt ist.
Du hast die Stunde vorher vergessen,
wenn wir gebraucht haben, unser Audioequipment vorzubereiten,
obwohl wir alle...
Ja, das ist halt am einen schlechten Mikrofon, aber...
Trotzdem sind wir noch nicht so weit gekommen
zu erklären, was überhaupt eine Hashmap ist
und wie sie funktioniert
Das ist irgendwas, wo man
ganz schnell nachgucken kann, weil man direkt weiß, wo es ist
Also man kann quasi dem Key
ansehen, wo er sein muss
oder so
Dem Key nicht, aber man kann aus dem Key was
rauskitzeln
Okay, aber aus diesem Rauskitzeln weiß man direkt, wo es sein muss
weil das irgendwie
Ja, der Trick ist
und der Trick ist im Wesentlichen schon im Namen.
Also man nimmt nicht die Keys selber, sondern man nimmt Hashes von Keys.
Deswegen muss es auch hashable sein.
Genau, deshalb muss es hashable sein.
Und weil eine Eigenschaft eine Hash-Funktion sein soll,
dass sie nicht vorhersehbar ist, bedeutet das auch,
dass sie gleich verteilt ist über den Raum der möglichen Hash-Ausgänge.
Das bedeutet, wenn ich aus einem Wert einen Hash mache,
und Jochen unterhalten sich über die Programmiersprache Python
macht da viele coole Tricks,
die
dir helfen. Magie.
Aber das ist bei einer Hashmap
immer so, die hat so einen Füllungsgrad,
wir haben es vorhin schon angesprochen, bei Python ist es
maximal zwei Drittel voll. Also Wurzel
drei, hast du gesagt. Wurzel drei
wäre noch besser, aber
das ist halt leider kein Integer.
Ist das der goldene Schnitt? Nein.
Nee, der goldene Schnitt ist
1,618 noch was.
Was ist Wurzel drei? Der heißt auch
V.
Brüssel 3 ist 1,7.
Das war knapp.
Vielleicht noch besser.
Ist übrigens auch interessant, weil
ternäre Logik wäre besser, weil das
an irgendeiner Zahl dran ist.
Ach, keine Ahnung, spielt keine Rolle jetzt.
Das Wichtige ist,
wenn ich aus einem
Diktionario rauslesen möchte,
dann nehme ich
den Key, den ich lesen möchte
und hashe den
und nehme dann diesen Hash
als Index in eine Liste rein.
Und wenn in dieser Liste an der Stelle was steht,
was nicht None ist,
dann ist es der Wert,
der zu diesem
Key gespeichert wurde.
Und umgekehrt,
wenn ich in eine
HashMap etwas reinschreiben möchte,
dann
mache ich den Hash aus diesem Key
und schreibe den Wert
in diese Liste
an der Stelle des HashIndex
rein. Und das ist sozusagen der Trick.
Ich berechne einen
zufälligen Index
in diese Liste,
weil der gleich verteilt ist, weil diese
Hash-Funktion gleich verteilt ist,
füllt die diese Liste gleichmäßig auf
und
kann dann
eben in O von 1,
weil diese Berechnung dieses Hashes immer
gleich lange dauert, diesen zufälligen Index
finden und dann da reinschreiben.
Jetzt gibt es ein Problem. Was ist, wenn
wenn zwei Keys auf den gleichen Hash-Index zeigen.
Und das passiert.
Wenn wir ein Dictionary haben, was acht Einträge hat,
dann ist die Wahrscheinlichkeit, dass zwei auf den gleichen Index zeigen,
vergleichsweise hoch.
Eins zu acht.
Das heißt, man muss sich eine Technik überlegen,
um sogenannte Kollisionen zu vermeiden.
Und da gibt es zwei Möglichkeiten.
Entweder kann ich sagen, jeder Eintrag in meinem Dictionary ist eine Liste.
das heißt, wenn zwei auf die gleiche Sache
hashen, dann muss ich halt durch diese Liste durchgucken
und da den entsprechenden Wert rausholen
das heißt Chaining
oder
man kann einen neuen Hash berechnen
und sagen, wenn da eine Kollision ist, dann
verändere ich meine Hash-Berechnung
und
wähle sozusagen einen neuen zufälligen Hash
und die Wahrscheinlichkeit, dass da eine Kollision auftritt
wird eben jedes Mal kleiner und das heißt
Open Addressing
und Python Dictionaries machen tatsächlich Open Addressing
das heißt die haben keine Liste
an jeder Stelle gespeichert
sondern die sagen halt wenn da eine Kollision ist
wenn das nicht der richtige Key ist den ich da gefunden habe
dann
muss ich diesen Prozess fortsetzen
muss einfach sozusagen nochmal
einen Hash berechnen
Ja da wird dann so ein
Counter mitlaufen gelassen damit man
eben wieder diese Eigenschaft hat aber sozusagen
diese Bits wiederverwenden kann
dass du nicht
in zwei Richtungen wächst sondern dass
deine Hash einfach nur in eine Richtung
Das sind Implementierungsdetails.
Aber das ist im Wesentlichen die Magie, dass man aus dem Key
einen Hash berechnet und dieser Hash hat eine gewisse
Eigenschaft und die heißt gleich verteilt.
Und auch wenn ich die auf
einen Index zusammendampfe, dann sind sie immer noch
gleich verteilt und das ist der Trick da drin.
Bedeutet halt, dass der Key hashable sein muss.
Es gibt eine ähnliche
Struktur, die heißt TreeMap.
Da werden die
Keys in einen Tree abgelegt.
Dann müssen sie nicht hashable sein, dann müssen sie sortierbar sein.
und dann habe ich halt einen Tree, dann habe ich Zugriffe, die alle logenden sind.
Genau, ich weiß nicht, ob es immer noch so ist,
die Hash-Map-Default-Implementation der Standard-C++-Bibliothek von Boost war irgendwie so ein Tree-Map
und hat dann irgendwie, als wenn man was optimieren wollte, dann ein C++ geschrieben haben
und dann war das überraschend von der Performance her, weil das war dann hinterher langsamer.
großartig
in Java gibt es diese beiden Optionen
unter diesen Namen, es gibt HashMap und es gibt
DreamMap, das heißt bei Java muss man sich immer
raussuchen, was man haben möchte
die Antwort ist immer HashMap, aber egal
und natürlich bei einer HashMap
ist das, dass man immer Hash-Funktionen haben muss
und Hash-Funktionen sind auch so eine Sache
die müssen schnell sein
und trotzdem gut und ich möchte gerne viele
verschiedene haben und
die sollen alle schnell sein und alle möglichst gut
und da die richtige Hash-Funktion
rauszufinden und eine gute Implementation
davon zu haben, ist nicht ganz einfach.
Welche wird verwendet?
Das weiß ich nicht.
Ich stelle die Frage.
Ja, das weiß ich nicht.
Es gibt ja so Hash-Funktionen, die kennt man ja. Es gibt MD5
und SHA-1 und SHA-256
und CRC32
und die sind aber alle nicht
geeignet dafür.
Und dann gibt es so welche, die kennt man überhaupt nicht
und die haben auch abgefahrene
lustige Namen, von denen ich jetzt keinen
einzigen sagen kann, weil ich kenne sie ja nicht,
die aber eben keine
kryptografischen Hashes sind, sondern eben solche
Hash-Funktionen, die man für solche Datenstrukturen verwendet,
die dann
halt aber andere Eigenschaften haben. Die brauchen dann nur
acht Cycles und geben
nur zwei Byte als Hash zurück oder irgendwie solchen
Quatsch, weil das hierfür
viel wichtiger ist.
Ich kenne die Hash-Funktionen für
für kleine Integers und die ist sehr einfach.
Die ist das Integer selber.
Also der Hash von 1 ist 1, der Hash von 2 ist 2.
Aber das wird dann, wenn die Zahlen größer werden,
ist das nicht mehr so toll.
Aber was ist der Hash von 128, Jochen?
Das glaube ich auch immer noch, 128.
Ich glaube, es geht nur bis 127.
Ja?
Ich glaube, Small Integer in Python geht nur bis 127.
Moment, Moment, ich habe doch hier die Rattle schon aufgemacht,
da kann ich auch gleich nochmal Hash 128.
Ich habe ja kürzlich ein paper.
Aber wenn ich 512
verdoppeln, war eine gute Strategie,
habt ihr eben gesagt.
512 ist auch immer noch,
bei 1024 auch immer noch.
512 ist bei Integers einfach immer so.
Nein, nein,
wenn die wirklich groß werden, dann ist es nicht so.
Okay, sie müssen wirklich groß werden.
Ich bin gerade schon bei einer Million, bei einer Milliarde.
Dann sind es vermutlich 32.
Über 32.
An signed in, man weiß es nicht.
Mal ein Minus.
Ah, okay.
Es gibt ja ein sehr schönes Paper, das heißt
People Mistake Knowledge on the Internet
for their own knowledge.
Du hast eine gefunden. Also, ich habe eine gefunden,
aber da musste ich jetzt schon irgendwie 20, 30 Nullen
hintendran machen. Ich weiß gar nicht mehr, wie das heißt.
Das sind die, die
früher L hießen. Das ist auch super.
Erstmal mal verdoppeln, also
12.420, dann 10.000, 100.000,
eine Million, 10 Millionen, 100 Millionen,
dann auf einmal so. Ich weiß nicht, wie die Zahl
jetzt da aufgefallen ist, aber ich weiß jetzt
doch, bis wo denn das wohl ist.
das ist wohl tatsächlich bis zur Grenze, bis zur 64-Bit-Grenze.
Weil das, was hier rausgefallen ist,
ist maximal 64-Bit.
Aber wo Zeit-Implementation-Decay sind,
das ist eigentlich Sines oder Unsines in Python?
Und was ist das in 64 oder in 32?
Sines meine ich.
In Python
die Integer sind Long-Integer.
Also 64.
Es gab früher eine Unterscheidung zwischen Long-Integer und Integer.
Die gibt es seit Python 3 nicht mehr.
Da ist jeder Integer eine Ganzzahl
und die verhalten sich auch korrekt wie mathematische
Ganzzahlen. Du kannst beliebig viele Stellen machen.
Die Implementation dahinter schaltet um
zwischen Integers und Long Integers.
Aber das ist ja nur ein
Implementationsdetail, das ist nur ein Umsetzungsdetail.
Hash von minus eins minus...
Hash von minus eins minus zwei, ja schön.
Interessant, okay.
Wieder was gelernt.
Die exakte Funktion spielt gar keine Rolle.
Wenn du Hash von irgendeinem String machst,
kriegst du halt auch irgendeine Zahl raus.
Das Wichtige ist eher, dass es schnell sein muss
und dass es deterministisch ist
und so weiter und diese ganzen Eigenschaften, die man
so stellt an
Funktionen und halt, dass
es gleich verteilt ist über die Menge der Hashes.
Und ich glaube, die Menge der Hashes, wenn du die Zahlen
vor dir hast, Jochen, die sehen aus wie 32-Bit-Zahlen,
oder?
Ja.
Minus 2?
Minus 4.
Nein, keine Ahnung.
Oh, HASH-1 ist gleich HASH-2.
Da.
Da hast du direkt eine Kollision.
und musste Open Addressing machen.
Ja, okay.
Ja, witzig, witzig.
Das heißt, kann man Dict-Keys,
wenn das Int sein können,
können das auch negative Int sein?
Ja, na klar.
Alles was Flash-Build ist.
Das heißt, wenn du minus 1 reinschreibst,
dann muss er tatsächlich eine Kollision machen
und minus 2, dann muss er quasi eine Ebene tiefer gehen.
Ja, okay.
Also man kann es auch deine eigenen Objekte
machen. Ja, genau. Das ist auch etwas, was ich gerne
mache tatsächlich.
und was Leute mal so überrascht,
wenn man dann Objekte als Keys hat,
dann sagen die immer so
Oh nein, das geht.
Das ist okay.
Du solltest dann eigentlich auch immer noch Frozen-Versionen machen.
Also musst du dann eine Methode an deine Klasse dran machen,
die hashable ist?
Ja, das muss natürlich hashable sein.
Und wie wird das hashable? Also was versucht der beim Hash denn zu machen?
Du implementierst einfach dunder hash.
Dunder hash, okay.
Dann wird dir aufgerufen und dann kannst du,
wenn du eine ID schon hast, dann kannst du die natürlich auch zurückgeben.
Oder du kannst halt, ja,
und das Bring Representation von deinem Effekt.
Jedes Objekt ist doch hashable, oder?
Die Objektidentität als Hashfunktion.
Ja, das kann natürlich sein,
dass das der Default ist.
Wie könnte man das jetzt schnell rausfinden?
Help, dann dann Hash.
Help, dann dann Hash.
Wie wäre das denn?
Aber du kannst natürlich
deine eigene Hash...
Scheint so zu sein, ja.
mal help, dann dein Hash.
Du kannst natürlich
deine eigene Funktion da reinschreiben. Das heißt, du kannst
eine Hash-Methode schreiben,
die für deine Objekte spezifisch ist.
Aber wenn du das machst,
wenn man seine eigene
Hash-Methode implementiert, dann muss
man wirklich darauf achten,
dass sich Keys in dem Dictionary nicht ändern
dürfen. Das heißt, wenn ich
einem Objekt
eine Hash-Funktion gebe,
eine Hash-Methode gebe, die sich
zwischendurch verändern kann, dann geht mein
Dictionary kaputt.
Und das geht dann auch
gleich richtig kaputt, weil dann finde ich gar nichts mehr
in meinem Dictionary.
Ja, ja, ja.
Also da muss man natürlich aufpassen.
Aber ich meine, oft hat man ja tatsächlich eine
ID, die man nehmen kann.
Und bei der Hash-Print-Tool, man rechnet das nicht selber
aus, sondern man gibt halt etwas zurück,
was dann durch Hash nochmal durchläuft.
Man fällt zurück auf irgendwas.
Aber dass man halt sagt, okay, eine Adresse
ist halt, der Hash einer Adresse ist der Hash aus der Straße und der Postleitzahl
und der Stadt. Das ist ja schon irgendwie naheliegend, dass du halt
irgendeinen wegbildest, was du dann hashst.
Und klar, das kann man natürlich machen.
In meiner Erfahrung tritt es nicht so häufig auf, aber wenn du sagst, dass du das gerne machst,
dann...
Mit Zusammenhang mit Data Classes,
beziehungsweise so Atos.
Dataclass ist ja automatisch hashable, oder?
Ja, bei Dataclass, das weiß ich gar nicht so genau.
Also ich habe das jetzt,
was ich jetzt im Kopf habe, ist mit Atos.
Da kann man dann auch solche Sachen sagen.
Man kann es natürlich selber implementieren, aber man kann auch sagen,
also es soll hashable sein
und diese Attribute will ich dafür verwenden
und die müssen dann natürlich auch in der Uni sein.
Und dann macht es manchmal Sinn,
weil dann kann man halt bestimmte Sachen
look-upen
mit einem anderen bestimmten Ding.
und dann ist es manchmal ganz praktisch.
Ja, das ist ja oft so,
dass man
seine Algorithmen beschleunigen kann,
wenn man so ein Lookup macht,
wenn es in dem Algorithmus vorkommt.
Wir hatten einmal so einen Fall
im Computerclub,
da war der Bison auch da und hat da eben seinen Algorithmus
mit einer Liste geschrieben,
wo er dann eben immer die Elemente aus der Liste raussuchen
musste, wo er immer nachgucken musste, habe ich diesen
Knoten schon besucht
in der Liste und das war halt O von N
und dann haben wir es umgebaut zu einem Set,
was
im O von 1 ist, wo diese Operation O von 1
ist und dann wird es halt deutlich schneller. Also wenn man
das braucht, ist das
schon ein super Power.
Ja.
Ja.
Hast du noch etwas auf deiner Liste stehen, Johannes?
Nee, ich habe jetzt tatsächlich meinen ganzen
Notizzettel
abgefrühstückt. Jochen, hast du noch was zu Dikt,
was wir noch nicht gesehen haben? Also ja, was ich
ganz gerne vielleicht noch
sagen wollen würde oder so, ist halt,
und dass man auch selber sich Sachen implementieren kann,
die dann halt so funktionieren wie Dix.
Es gibt ja seit Python 3.3, glaube ich,
Protocols oder was weiß ich wie das.
Man hat halt auf jeden Fall diese F-Sec-Base-Classes,
wo es dann Interfaces für diese ganzen Geschichten gibt.
Und da hat man dann halt...
Moment, also Protocols sind
fertige ABCs, F-Sec-Base-Classes
für die Implementierung
von Python-Modulen,
die es schon gibt?
Ach, cool. Die kommen ja auch fürs Typing der Modus.
Ja, genau. Und die sind großartig fürs Typing.
Da kann man nämlich richtig gutes Ducktyping
machen, was aber trotzdem getypt ist.
Genau, und dann kannst du eben
für deinen Anwendungsfall
etwas Spezielles hinbauen, wo du dann sicher sein kannst,
dass sich das dann aber genauso verhält und
auch an den Stellen verwendet werden kann,
wo du normalerweise ein DIC benutzen würdest.
Da kannst du auch sehr coole Sachen mitmachen.
Wobei das Protokoll
von einem DIC-Tiering ist ja vergleichsweise groß.
Was ist das denn?
Das ist, meine ich, mappable, aber
ich gucke mal gerade, wo haben wir das denn da?
Es gibt Mapping.
Mapping heißt das, genau.
Ein Mapping. Mutable Mapping.
So,
ach, jetzt steht das Interface
hier aber nicht dabei.
Collections.abc
Import. Abstract
Base Class. Moment, ich importiere
das gerade mal. Mach mal ein Diagramm. Ja, das ist cool, weil dann kannst du
einfach von Mapping ergen lassen und alles, was du nicht implementiert
hast, wird dann einfach direkt geraced.
Genau. Wenn das halt
nicht da ist.
Beziehungsweise ein MyPy oder ein TypeChecker sagt dir der auch
direkt das. Ja, genau. Du wirst direkt gezwungen, das richtig zu
implementieren.
ABC Broad Collections.
Ja, ich habe mich gerade geschützt.
Weil ABC ist ja die ABC selber drin.
Ich weiß, ich weiß.
Gleichzeitig reden, tippen
und das alles.
Mach mal ein neues Objekt
von Mapping auf, einfach.
Das kann ich nicht
interessieren.
Das geht nicht.
Genau, da steht aber jetzt dann, was du brauchst.
Ja, okay.
Ich muss da GetItem, Itter und Längen definieren
von meinem Wrapping.
Okay, zumindest. Also das Interface
selber ist jetzt doch etwas größer. Das sind halt
37
Methoden und das ist natürlich
schon eine ganze Menge. Ja, das hatten wir ja vorhin auch schon
angesprochen, dass eben Dicts relativ
viel Oberfläche haben.
Weil sie halt für alles verwendet werden.
Ja.
Ja, aber eben.
Also man kann das halt verwenden.
Interessant, interessant.
Ja
Ist das euer Lieblingsdatentyp?
Ja, also von den primitiven Dingen
auf jeden Fall, ich hab das auch letztens
diese ganzen Type-Hints
Typisierungsgeschichten
die es jetzt neuerdings gibt, es gibt ja immer so
auf Twitter gibt es dann so die
alten Säcke, die da rumhängen und
die äußern sich
Wie alt bist du gleich noch?
Wie jung genug war
Ja, sie sind noch alt
Die im Kopf alten Säcke
Ja, nee, also
verdiente Veteranen
Ah ja, ja, ja, okay, sehr schön, sehr schön auch
der Python Community und
die sich manchmal so ein bisschen despektierlich äußern
was so, was diese ganzen
neuen Entwicklungen angeht, ja
Die ganze Scheiße ist gar nicht mehr Pythonic
Genau, und so ein bisschen kann ich das natürlich auch, kann ich das nachvollziehen
muss ich sagen, also zum Beispiel, ich sag jetzt mal
einen Namen, David Beasley zum Beispiel
der ganz viel cooles
Zeug gemacht hat, der auch eines der besten
Bücher, Python Bücher geschrieben hat, irgendwie
Essential Reference, glaube ich.
War lange super. Jetzt gibt es
da sogar Python Distilled. Ist jetzt
nochmal eine neue Ausgabe.
Super Buch.
Und der sagt so, also
ich weiß nicht, dieses ganze Typing-Zeugs,
ich finde, das sieht nicht gut aus.
Ich mag das nicht. Und was wir
früher, als wir nichts hatten, was wir gemacht haben,
wir haben immer irgendwie Dicts genommen
und ein paar List Comprehensions und damit haben
wir alles gemacht. Alles haben wir damit gemacht.
Und das war viel besser, als wenn einer sich mit
Java hingesetzt hat und dann irgendwie so
angefangen, erstmal Interfaces zu definieren
und dann irgendwie, keine Ahnung,
sich erstmal in
so ein
Spinnennetz aus komischen Dingen,
die man alle so machen muss, weil man sie halt machen muss,
hinschreibt, genau,
Getter, Setter, dieses ganze Zeugs.
Dann hat man sich in so einem Spinnennetz von Dingen
verheddert, bevor man auch nur
eine Teile produktiven Code geschrieben hat.
Und dann ist man mit den Dicks und den Lisp Comprehensions
so lange fertig.
Und damit hat er nicht so ganz Unrecht.
Tatsächlich ist es so, dass Dicks, wenn man das beherrscht,
und so wirklich verstanden hat, wie das funktioniert,
mit eben vielleicht noch
DigComprehensions, vielleicht noch
GeneratorExpressions würde ich dazu nehmen und
ListComprehensions. Damit kann man
einen Großteil von dem, was man so
im Alltag an Programmierproblemen hat,
tatsächlich lösen und
es ist sehr, ja,
man kommt da schnell hin.
Sehr convenient und halt dem Python-Prinzip eigentlich.
Simples, better than complex.
Das ist auch so ein bisschen die Stärke
von Python.
Ich muss auch
gelegentlich andere Sprachen machen, jetzt so ein bisschen
TypeScript kommt auf mich zu und
C Sharp
und da sind solche Mapping-Typen
einfach unhandlich, die sind einfach
schwieriger zu benutzen.
Du musst definieren,
was da für Typen drin sind, nicht in TypeScript.
In TypeScript kannst du einfach,
der Trick an TypeScript, kannst du einfach immer Annie sagen.
Jeder Typ ist Annie
in TypeScript, aber in C Sharp
kannst du es auch machen, kannst du auch
Annie sagen, aber
wird nicht gerne gesehen.
Also mein letzter Lippet Andy übrigens, der sagt, das reicht ihm nicht.
Ja, okay, gut.
Das ist eine Einstellungsnachricht, das kannst du ja abschneiden.
Ja, kann ich.
Das geht trotzdem.
Aber es ist einfach unhandlicher und das ist auch sowas, wenn man sich an diese Art zu denken gewöhnt hat,
dann sieht man auch überall Dictionaries.
Und dann will man sie auch überall verwenden.
Deshalb mir fällt die Schauprogrammierung sehr, sehr schwer, weil ich mir ganz oft denke,
ja, da könnte ich jetzt einen Dictionary verwenden, aber kann ich an der Stelle nicht.
und muss aber zwölf Umwege
machen.
Ich sehe aber auch, also
ich sehe auch den Vorteil von diesen Typingern.
Ich bin da ganz klar
auf der Seite der jungen Hüpfer wie dir, Jochen.
Und das ist für mich so ein bisschen
diese, es gibt ja diesen klassischen
Kampf zwischen Explore and
Exploit,
wo jeder entscheiden muss,
was er machen muss, um
um ein Problem zu lösen.
Explore heißt unbekannte Dinge angucken
und Exploit heißt bekannte Dinge so lange gegenhauen,
bis es irgendwie kaputt geht.
Ja genau, also Explore heißt Lösungen ausprobieren,
die dir selber noch nicht bekannt sind.
Also suchen quasi.
Und Exploit heißt Dinge anwenden,
die du schon weißt.
Und Menschen
sind da halt sehr unterschiedlich und das ist tatsächlich
wohl so, dass das mit dem Alter
eher zu Exploit geht als zu Explore,
was ja auch okay ist, weil du viel Explore schon
gemacht hast und dann eben
die Dinge anwendest, die du schon weißt. Wenn du mehr weißt,
ist das natürlich effektiver, als wenn du weniger weißt.
Kinder machen viel, viel mehr Explore.
Ich wusste, dass einige Hacker schon von Anfang an
Greise im Kopf gewesen sind.
Ja, das...
Man muss sich das auch manchmal wieder
zurück in den Kopf rufen, dass man vielleicht
gelegentlich wieder Explore machen muss. Das ist auch
der Grund, warum ich C-Sharp und TypeScript und so weiter mache,
damit man mal ein bisschen wieder was anderes macht.
Ich dachte, C-Sharp machst du, damit du endlich noch ein Spiel
realisieren kannst. Ja,
irgendwie muss man ja sein Schloss sicher
arbeiten.
Wie erschlossen arbeiten?
Das spricht sich doch schon von alleine.
Ja, erben,
ich glaube,
wird bei mir schwierig.
Oder erobern. Schlösser müssen eigentlich geobert werden
mit Verteidigungsanlagen. Oder heirat.
Ja, das ist auch eine Art
der Eroberung.
Ja, das ist eine gewisse Art.
Sieht bei mir jetzt
so gut aus. Ich bin schon
verheiratet und mit Erben.
Ich habe meinen Vater gefragt, aber
im Inventar.
Hast halt die hübsche genommen, ist ja eine schlechte Entscheidung.
Absolut.
Und hübsch und schlau, das sind ja schon zwei Ereignschaften,
die man sonst nicht im Paket kriegt.
Hat mich mein Vater gefragt, wann du das Erb
direkt die Schlösser austauschen lässt.
Ja, aber das ist eben, man muss
sich auch immer wieder in den Kopf rufen,
dass man ein bisschen Explore macht und nicht nur Exploit
also nicht nur das anwenden was man kann, sondern auch mal was
ausprobieren was man noch nicht kann
und Dictionaries und Typing
gehören halt
dazu. Es gibt so eine
witzige Liste von
wie man Programmiersprachen beschreiben kann
und die fangen alle an mit
What if everything was
und C zum Beispiel
bei C ist das Mandat
What if everything was a pointer und in Java
ist What if everything was an object
und Python ist halt
What if everything was a dictionary?
Und das ist schon so. Dictionaries sind so ein bisschen
der Kern von Python.
Die sind leicht zu verwenden, die sind sehr mächtig,
man kann so gut wie alles damit machen und
die
formen dann so ein bisschen das Denken.
Das ist aber ein bisschen verherrlich, wenn man jetzt noch gar nicht die Nachteile
davon erklärt. Warum will man das denn vielleicht
nicht benutzen?
Es könnte es jetzt noch für Nachteile geben.
Es ist O von 1, es kann alles speichern,
das ist großartig. Also vielleicht so ein
Speicherverbrauch.
Ja, das haben wir am Anfang schon gesagt.
Also ein Dictionary verbraucht direkt ein Viertel Kilobyte.
Das heißt bei so einem Vetted Programming oder irgendwelche so IoT Sachen ist es dann vielleicht nicht die richtige Wahl.
Es ist auf jeden Fall relativ wasteful.
Also man hat immer einen großen Overhead.
Immer mindestens 40% Overhead.
Wir laufen alle auf so Kisten, wo wir genug Speicher haben, da ist das wurscht.
Ja, natürlich. Das ist die Ausrede, die man heutzutage macht.
Aber es gibt natürlich auch Fälle, wo es eben nicht so der Fall ist.
Oder wo man an die Grenzen kommt.
wo man eben
eine Waschmaschine hat halt für 4 KB
Hauptarbeitsspeicher
Wenn du 1000 TPS machen kannst statt eine Million
und du brauchst dann eine Million, dann
wird das halt schon irgendwann relevant
Ja, Moore's Law
wird alles gut machen, langfristig
und auch eine Waschmaschine bekommt
mehrere Gigabyte Speicher
für einzelne Waschprogramme
Wir haben ja heutzutage schon mehr
Hauptspeicher
Irgendwann musst du da einfach nur noch so Grundrohstoffe reinkippen
wie Sand und Salz
oder sowas und da baut es automatisch
Waschmittel raus und das
perfekt für die Wäsche geeignet ist.
Du kannst doch schon
so Waschmaschinen, Waschmittel,
Cartridges kaufen und die werden dann auch
so dosiert, dass es für den Waschmittelhersteller
optimal ist.
Für den Waschmittelhersteller,
das ist natürlich, ja egal.
Ja, leider nicht.
Ich hoffe euch hat eure Folge, unsere Folge zu Dicts
heute gefallen. Falls dir noch irgendwas dazu einfällt,
dann...
Pics und sowas machen wir irgendwann anders.
Ja, ich glaube, wir sind jetzt heute weit fortgeschritten.
Also mein Lieblingsmodul
in Python ist ja
Buildings.dict. Das ist mein Pick der Woche.
Okay.
Ja, ich mache dann einfach von einem Pedantic.dict.
Ja, okay, perfekt.
Und Jochen macht Name-Tubel.
Ja, Adress, ja.
From Jochen Imports.
Die eigene Implantierung.
Aber genau, kann man sich auf jeden Fall auch mal angucken.
Das lohnt sich.
Da haben wir doch was gemacht.
ging schnell
ja dann bleibt uns gebogen
hört uns immer wo ihr uns hören wollt und
eine schöne Zeit und bis zum
nächsten Mal
Tschüss