Transkript: Was, wenn alles ein dict wäre?
Vollständiges Transkript der Episode. Zeitstempel beziehen sich auf die Audiowiedergabe.
Ja, hallo liebe Hörerinnen und Hörer.
Willkommen 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.
Halli, hallo, 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 es sonst noch so einfällt.
Und dann gehen wir so ein bisschen in das Thema rein.
Ja.
Also du wolltest unbedingt auch über den Copilot reden, habe ich gehört.
Ich wollte das.
Ja, ich ja auch.
Der Johann ist derjenige,
der immer darüber sprechen möchte.
Ja, wir haben schon zweimal drüber gesprochen.
Aber jetzt hat auch Jochen ihn ausprobiert.
Jetzt hat auch PyJarm hat jetzt auch Copilot.
Deswegen, genau.
Genau, ich habe irgendwann die erlösende Mail von GitHub dann 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 so vorgeschwärmt hast.
Ja, du hast mal gesagt, ach, was für ein Fach ist ja völlig egal.
Das kann ja nicht, also wenn man jetzt irgendwie so den durchschnittlichen Code da von irgendwelchen 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.
Ja, sogar Jochen findet es hilfreich.
Ja, ich finde es auch sehr, sehr cool.
Also ich finde vor allem dieses Auto completion cool.
Er lernt irgendwie aus seiner eigenen Codebase und weiß so ein bisschen, was du als nächstes vorhaben könntest oder macht manchmal so einen guten Vorschlag.
Ist natürlich nicht immer, ist auch nicht immer richtig, aber manchmal ist es erstaunlich richtig.
Ja.
Ja, und manchmal findet man halt Dinge dadurch erst, die man also ich hab, ich mache jetzt manchmal auch so ein bisschen JavaScript bzw.
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.
Ja, klar, das ist halt richtig.
Also du musst halt wirklich aufpassen, was für einen Namen du denn Ding gibst.
Wenn du den gute Namen gibst, ist er viel besser, als wenn du schlechte Namen gibst.
Und wenn du zusätzlich.
Da muss man sowieso aufpassen und immer gute Namen drin.
Genau, aber wenn man das dann halt macht und dann auch einen guten Doc-String schreibt oder einen Kommentar dazu, dann lernt er sogar noch aus diesen Doc-Strings, aus den Kommentaren was dazu.
Oder halt, also was halt bei mir voll gut funktioniert, ich mache halt den Methodennamen beispielsweise oder den Klassennamen oder die Funktion und die Argumente und Type-Ns und dann weiß er ziemlich oft, was zu tun ist, wenn ich einen DocString noch mache.
Dann schreibe ich im Docspring 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 sehr gut.
Und ich weiß, warum Joch den gut funktioniert, weil er sich halt immer am selber am eigenen Code-Repo orientiert und der orientiert sich an Jochens eigenen Code und dann denke ich Joch natürlich immer, oh, was für ein
toller Vorschlag, ja.
Ja, ja.
Nee, aber es ist ja immer eine, also Kritik würde ich sagen, also ich habe, es ist auch besser geworden, wenn man diese Nightly-Version nimmt.
Ich habe zuerst die Standard-Version genommen, die, und man kann halt die aktuelle Bleeding-Edge Geschichte nehmen, die ist, äh, finde ich, nochmal ein gutes Stückchen besser.
Was manchmal nicht so gut funktioniert, also was womit Copilot halt irgendwie unerwarteterweise, weil man denkt, das ist ja eigentlich eine eine fache Geschichte, große Probleme hat, wo er das ein großes Problem hat, sind Klammern.
Also die Klammern richtig zu setzen, also zum Beispiel zumachen, das macht eigentlich fast nie die 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.
Okay.
Kannst du das machen?
Kannst du dir das nicht erklären, dass das 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 das funktioniert vielleicht nicht so richtig.
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 Rente.
Na gut, aber 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.
Nur das ist halt irgendwie so ein bisschen erstaunlich, wo man sich denkt, so, naja, also den schwierigen Teil, den kann es eigentlich überraschend gut.
Nämlich irgendwie rausfinden, was man da machen wollte und dann den so Code schreiben, der zumindest so aussieht, als würde das nicht mehr.
Ja, machen wir eine Klammerfehler.
Und dann kommen halt so Dinge, wo man sagt, das kann man ja fast, eine Idee kann das ja schon, so die Klammern richtig setzen.
Und das geht da 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, das so User-Daten enttäuscht.
Beispielsweise machst du irgendwie eine JSON auf und dann irgendwie zwei einen Namen, eine E-Mail-Adresse oder sowas und ein Passwort.
Oder machst du Autocomplete und dann machst du dir halt eine Liste von Usern irgendwie, die mit Nutzernamen, Passwort und so.
Das ist schön.
Das ist halt dann die Frage, so wieder.
Hast du direkt Demo-Benutzer, perfekt?
Generiert oder?
Ja, oder sind die generiert oder echt?
Man weiß es aber nicht so genau, von wo die sind, dass das schon sind.
Die haben alle gelernt.
Ja, es ist wohl auch, wenn man so Zahlenfolgen eingibt, dann gibt er einem interessante Instruktionen.
Das haben wir jetzt noch exit.
Hand einen Screenshot gesehen, wo der ein russische Funktionsnamen dazu kam.
Also, oh, okay.
Ja, ich bin ja mal gespannt, was dabei rauskommt, wenn man sowas, man anfängt irgendwie so 3.1417.
Ja, ja.
Hab mich hier nachgemacht, warte, ja.
Ja, ja, vielleicht, vielleicht.
Also, ja, das ist ja.
Es ist noch keine AGI, es ist noch keine generelle Intelligenz,
glaube ich.
Da habe ich letztens, äh, ach, ich komme vom Holzchen aufs Stöckchen, aber vielleicht ist das ja auch nicht so uninteressant, wieder eine ganz, ganz netten, netten Podcast-Episode gehört mit Lex Friedman, äh, Wolf, Lex Friedman, Stephen Wolfram von Wolfram interviewt hat, genau.
Ja, der ist ja so ein Wunderkind und dann so ein bisschen hinter dir am Arbeiten.
Ja, polarisierend.
Warum?
Jetzt muss das genau aufklären, direkt.
Ja, es gibt Leute, die lieben ihn total und er 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
diese andere Nummer.
War das nicht Rule Rule 38 oder so?
Das ist die.
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.
Steven Wolfram sagt halt mehr oder weniger, der schreibt ganze Bücher darüber, ja, was diese State-Maschine alles kann und dass die das Universum encodiert.
Und das ist natürlich.
Wenn du die gesamte Wissenschaft umstellen willst auf State Machines, ist es.
Also ich habe immer noch keine Ahnung, was Rule 38 ist, aber das Urban Dictionary hat mir gesagt, Rule 38 is a prison offense in which someone is masturbating in public.
Ah, ja, okay.
Wenn man Spaß haben, wenn du so einen Private Modern hast, dann google doch mal nach.
Rule 34, das ist, glaube ich, die.
If it exists, there's pawn of it, glaube ich.
Das ist auch irgendwie eine sehr wichtige Regel und tatsächlich stimmt sie halt einfach immer.
Aber.
Leider, leider erstaunlicherweise.
There's a type of pawn, there's a website for it.
Achso, okay.
Das ist auch Rule 38, bestimmt hier.
Rule 30 sagen die, dass
das dann.
Okay, aber das sind beides nicht die Regeln, die ich jetzt gerade meinte.
Regel 30 ist es.
Genau, ne, aber genau, um diese Dinger ging es natürlich bei der Episode auch.
Und also ich finde das schon interessant, ja.
Ich meine, das ist ja, also er hatte irgendwie, Leute hatten hohe Erwartungen an ihn, weil er war halt so ein Wunderkind.
Und dann ist aber irgendwie da doch nicht irgendwie so wirklich so einsteinmäßige Ausmaße, haben seine Theorien da jetzt nicht angenommen, sondern eher so ein bisschen hinter den Erwartungen zurückgeblieben.
Und aber tatsächlich ist er ja, genau, eben der Meinung, dass er hatte ein Buch geschrieben, das hat auch schon so einen Titel New Kind of Science.
Das kann man ja auch nur nehmen, wenn man denkt, da hat man jetzt mal echt was gefunden.
Er hat ein gewisses Selbstbewusstsein, da kann man
nichts kennen.
Aber er hat ja auch coole Sachen gemacht.
Also so ist es nicht.
Also es ist nicht nur.
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 es ist der erschlägt es einfach durch Produktivität, diese ganzen Kritikpunkte.
Ja, also er hat ja auch so eine Firma, die macht Mathematik, auch eine super Software.
Ja, oder eben Wolfram Alpha, wie gesagt.
Und Wolfram Alpha, genau, ja.
Und ja, auch die Firma so zu nennen, also naja gut, aber das ist macht ja wirklich cooles Stock.
Also so kann man eigentlich auch nichts sagen.
Und das fand ich mir ganz interessant, weil es jetzt, weil er auch da dann, weil 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.
Du meinst Tau halbe?
Ja, genau.
Ja, stimmt.
Tau ist dann vielleicht etwas, was man häufiger noch braucht als Pi.
Und genau, wie ja, wie jeder weiß, ist das Ding halt transzendent, irrational.
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, jetzt okay, nicht mal die Verteilung der Ziffern da drin sagen kann.
Und die so aussieht, als wäre sie, als könnte man wirklich nicht, man kann es halt auf nichts anderes reduzieren.
Man kann da drin, findet daran keine Muster.
Oder ja, die muss, also da kommt einfach alles, was es überhaupt ein Mustern irgendwie gibt, kommt wohl offenbar daran vor.
Und das ist halt, ja, die Frage ist halt, wie kommt aus so etwas, aus so einer einfachen Regeln, wie man Pi bilden kann, warum fällt da plötzlich so ein ganzes Universum raus?
Ja, das ist ja, also 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 30ste, 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 ein generelles, 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, chaotischen Sachen produzieren.
Und das ist was sehr Erschreckendes und es 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 dich 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, überhaupt nicht bekannt sind alle.
Also du kannst sie ja nicht kennen, das ist ja so ein bisschen.
Aber man weiß halt nicht.
Es könnte ja sein, dass irgendwann keine neuen mehr vorkommen.
Einfach gar keine mehr.
Ist das normalerweise so beim.
Ja, okay.
Nee, ist eben nicht normalerweise so.
Aber es könnte sein, wir können es nicht ausschließen.
Das ist die Sache, was der Joch sagt.
Keine Ahnung.
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 VP entwickelt wird, hinschreibt und eine Funktion, die VP ausrechnet, das ist wirklich so ein paar Zeilen.
Da muss man diese Zeilen nur ganz, ganz lange und genau angucken und dann muss er doch irgendwie, muss einem doch klar sein, okay, ach, ab der da irgendwie neun, die kommen genauso häufig vor wie alle anderen auch.
Oder zumindest ist man immer mal wieder eine 9 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 es 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 so ein Witz unter Mathematikern, wo man Leute leicht auf die Palme
bringen kann.
Dann aber einfach nochmal kurz die ganze Unbeliegende.
Was ist denn Pi?
Pi ist das Verhältnis zwischen dem Radius eines Kreises und der Fläche des Kreises.
Und 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, ja, 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 halb mal 1.
Dann gibt es irgendwelche ganz leichten Formeln.
So 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 kein 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, ja, 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.
Ne, es gibt keinen Zahlen.
Gibt es nicht?
Also es bewiesen, 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 Eulersche Zahl.
Die Eulersche Zahl, genau, und die hat nicht ganz so eine einfache Erklärung.
Sehr gut, Dominik.
100 Punkte zusätzlich.
Die hat nicht ganz so einfache Eigenschaften, die sind nicht ganz so einfach zu erklären, aber ist auch transzendent, ist auch, man weiß auch nicht, ob es 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 ja, in gewisser Weise haben die jetzt auch was mit eben diesen ganzen theoretischen Informatikschichten zu tun, weil sie sozusagen in gewisser Weise berechnungstechnisch irreduzierbar sind, sozusagen.
Also man kann halt nicht eben, ja, also man muss es halt.
Es gibt keine geschlossene Form.
Ja, man muss sie tatsächlich ausrechnen, sonst sonst kriegt man sie halt nicht in den Griff.
Und das Problem ist, das ist halt teuer, ja, die auszurechnen, da muss man halt.
Ja, und das ist ja auch so ein bisschen ein Sport, ja, dass der die meiste Anzahl Stellen von Pi ausgerechnet ist.
Ja, da gab es letztens irgendwie wieder eine Nachricht, dass da jemand hier 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 Smarthead 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 meine, ich meine, kennengelernt, der hat sich als auch Hobbyaufgabe gemacht, Nachkommastellen von Pi auswendig zu lernen, halt, glaube ich, die ersten 250 auch sagen können.
Okay, das ist schon mal nicht so schlecht.
Wir haben doch alle so einen Freund, oder?
Der sowas.
Ja, es gibt auch irgendwie die Gesellschafter Freunde von Pi, glaube ich.
Und da muss man irgendwie die ersten 100 Stellen auswendig können oder so, damit man da aufgenommen werden kann.
3,1, 4, 2, wie geht das weiter?
Ja, 3,1, das ist schon ungefähr richtig.
Wie da ist, 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 irgendwie der letzten zehn Jahre alle falsch.
Sehr schön, sehr schön.
Kann man 3,142 sagen oder ist das auch immer falsch?
3,1415 ist so die Standardweise, aber es ist eigentlich falsch, weil es geht ja mit neun weiter.
Wenn man Pi, ich glaube, auf 15 Stellen genau hat, dann reicht das schon für alle physikalischen Sachen aus, weil das dann irgendwie schon im Nanometer-Bereich 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 1%.
Also das ist dann schon schon eine ganze Menge.
Okay.
Jede Programmiersprache hat eine Konstante, der 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 da hast gerade einen Bogen zu Python gedacht, ich bin nicht begeistert.
Ja, wunderbar, oder?
Ja, ja, sollten wir vielleicht irgendwie mal zurückkommen.
Ach, das ist aber wieder so völlig unvorhergesehen, aber ich finde das eigentlich halt so.
Das sollte doch heute eine
wenigsten Episode sein, oder?
Ja.
Da bist die Lot halt durch.
Wenn man in die Möhre ran will, da muss man auch ab und zu mal irgendwie keine Ahnung.
Man muss ja erst ausgraben, die Möhre.
Ja, Rotten.
Gibt es noch was am News?
Am News, ich weiß nicht genau, ist irgendwas Interessantes passiert.
Django ist jetzt gerade die Pre-Release irgendwie.
4.0 ist der Pre-Release.
Das hatten
wir komisch.
Ja, da war 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, mit letzte Folge hieß Python 3.10 Jahre.
Ja, gut.
Dann ist es trotzdem, ich wiederhole mich, es ist immer noch aktuell und immer noch cool.
Okay.
Ja.
Es gab ganz nette Artikel, einmal so über Python im Bankenumfeld gab es einen, der irgendwie in einer Variante hat,
denkt 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.
Die hat beschrieben als ein Fork des kompletten Bankten Python.
Bank Python, jetzt habe ich es aufgefangen.
Bank Python.
Großartig.
Ich habe diesen Artikel gelesen und ich fand den super.
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.
Genau.
Cale Peterson.
Und das 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.
Barbara.
Das sind schon viele Dinge, die man sich mal überlegen könnte.
Ja.
Den hast du vermutlich in meinen Weeknotes gefunden, oder?
Ja, genau, ja.
Werbung machen für eigene Sache.
Ja, richtig.
Ja, ich häng mit meinen Weeknotes wieder total hinterher.
Ich muss da unbedingt was machen, aber ich habe irgendwie keine Zeit, das ist schrecklich.
Das muss Teil des Prozesses werden.
Das muss eine Gewohnheit werden.
Du hast ja nichts zu tun, ja, alles.
Ich habe genügend zu tun, aber ich habe immer noch genügend Freizeit, dass ich Reddit lesen kann.
Und wenn ich statt Reddit Weeknotes schreibe, dann ist das doch ein Gewinn für uns alle.
Ja, das stimmt.
Ja, so viel Freizeit habe ich leider nicht.
Warte mal, warte mal, Dominik.
Haben wir nicht erst Montagabend von 20 bis 24 Uhr Computerspiele gespielt?
Ist das Freizeit?
Nein, das ist Socializing.
Und das war erst um 20.36 Uhr haben wir angefangen.
Oh ja, gut, okay, dann.
Ja, und dann dran gespielt haben, habe ich natürlich nächsten Morgen noch was 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 will es nicht lügen, bei 98 raus.
Und so sieht es auch aus.
Es ist trotzdem super.
Es gibt eine Max R, es ist eine Gehektorvision.
Wenn man die Original, in Original-Videos und Sprites und sowas noch hat, ist gar nicht so schlecht aus, finde ich.
Naja, das
Interface, also das ist oft so.
Diese alten Sachen haben oft gute Ideen, aber schlechte Internet.
Und passiert das mit unheimlicher Komplexität.
Das ist das aus der 96 Tonnen.
Ha, ehrlich.
So alt.
Fast so alt wie ich.
Ja, wir haben es geliebt.
Ja, und wir spielen das auch übrigens noch weiter, die nächste Johannes.
Ja, okay Gott.
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, machen wir Python-Dictionaries und so, ne?
Ja, heute entspannt.
Ihr wolltet heute über Dictionaries sprechen.
Ich habe es 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 Dictionary?
Was ist denn das, was ein Python ist?
Erstmal ein zweifte geklammertes, definiertes Objekt in Python, also dass es kein Z ist, sondern dass 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 das, wie im Python Dikt man 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.
Ja, 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 es ist ja die Frage, ob du, wie du das strukturieren möchtest.
Also die 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 an.
Aber wir haben nur einen, oder?
Du kannst ja ein Tupel reinpacken.
Okay, ich kann Tupel reinpacken, aber ich könnte mir jetzt nicht zweimal zu dir zwei verschiedene Sachen merken.
Also das müsste ich dann selber machen.
Nee, tatsächlich.
Also ein Key muss ist unique in einem Käfig.
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 es dann so, dass dann, wenn du das Lookup machst und dann Dominik nachguckst und dann gibt es verschiedene Dominics, dann hast du erst eine Liste von Dominics, die du zurückkriegst und in dieser Liste stehen dann die einzelnen Dänder drin.
Ja, aber ich kriege ja keine Liste.
Wenn man Dominik nachguckt, dann kriege ich nur einen Wert.
Der kann dann eine Liste sein.
Genau, aber wenn es eine Liste ist, ja, aber dann der Unterschied zum Telefonbruch ist ja marginal, du musst ja einfach nur gucken, dass ein oder mehrere Werte und dann jeweils dann wieder weiterpacken.
Ja, also ich
finde, es ist fürs Verständnis her schon ein sehr wichtiger Unterschied.
In einem Dictionary kann jeder Eintrag nur einmal vorkommen, jeder Key kann nur einmal vorkommen.
Okay.
Also ich habe tatsächlich irgendwann nochmal mit dem Kind.
In Müller gibt es sehr viele verschiedene Müllers.
Ja gut, aber wenn du Müller dann alle Liste von allen Müllers bekommst, dann ist ja der Zugriff auf einen einzelnen Müller genau wieder, dann müsstest du eigentlich nur eine Ebene tiefer rein.
Egal.
Also was ich da so tiefer drin verstanden habe, dass es irgendwie halt in den Speicher gemerkt wird und das deswegen so schnell ist, weil er dann einfach dann die Speicheradresse nachschauen kann.
Ja, das ist ja die Magie des Hashtable.
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ß, dass Stringsples sein können.
Ich weiß, dass es Integers sein können.
Noch was?
Strings auch?
Ja, genau, Strings habe ich gesagt, Strings, Insig.
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.
Das frage ich dich, Dominik.
Das weiß ich nicht, immer ausreichend.
Die Regel ist, tatsächlich ganz interessant, ein Key von einem Dictionary muss etwas sein, was sich nicht verändern kann.
Hashable sind diese Typen alle, aber der Hash kann sich verändern, wenn sich das Objekt verändert.
Und deshalb gibt es für Dictionary, äh, 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ändern kann.
Für Dictionaries und für Sets gibt es einen äquivalenten Datentyp.
Der heißt Frozen Dict und Frozen Set.
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 Frozen Set 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 weil man das machen will, ist weil man ein Lookup haben will nach dem Motto, wenn das da drin ist, dann gibt mir dies.
Ja, aber 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.
Oder die Reihenfolge spielt keine Rolle.
Das ist ja, das ist so ein bisschen, als Mathematiker ist das Set wie eine Liste ohne Reihenfolge.
Und interessant, Reihenfolge müssen wir es auch merken, weil Order Dict und sowas, weil das ja früher nicht so ging, das glaube ich an die Freude.
Ja, muss man inzwischen nicht mehr.
Früher musste man sich Order Dikt immer merken, aber inzwischen sind alle Dicts Order Dicts, deshalb, den Typ Order Dict gibt es noch, aber der macht irgendwie gar nichts mehr.
Ja, doch, doch, doch.
Der hat noch ein Reversed, aber.
Ja, doch, der hat, die verhalten sich unterschiedlich.
Also tatsächlich macht das durchaus Sinn.
Also man muss ab und zu mal, das ist vielleicht so ein bisschen, vielleicht sollte man das nicht müssen, aber je nachdem, wie man, wie man Dikt verhält, äh, äh, wie sich das Dikt verhalten soll, das man verwendet, also wenn man zum Beispiel viele Insatz hat von Keys, dann ist es besser, Order Dikt zu nehmen statt dem Default-Ding.
Also es gibt da tatsächlich subtile.
Warum Jochen?
Wie wächst es denn?
Wie wächst denn ein Dictionary?
Ja, genau.
Ich habe es vorhin nachgeguckt.
Soll ich es euch verraten?
Ja, verbindet.
Ja, aber ich hatte eh mal.
Ein Dictionary fängt an mit null Buckets.
Wenn du ein leeres Dictionary hast, das ist tatsächlich speziell.
Es hat null Buckets.
Es verbraucht 64 Byte.
Ist übrigens unterschiedlich zwischen 32 und 64-Bit Maschinen, aber ich glaube, wir sind alle inzwischen auch 64-Bit angelangt.
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.
Wobei das heißt quasi der Speicherbereich wird vorreserviert für alles, was wir rein haben.
Genau, diese Datenstruktur, das heißt, die heißt Hash Map 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.
Bei dem Array-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, dass er quasi sozusagen wie eine Liste bloß halt statisch getypt.
Und man verbraucht tatsächlich nur den Platz, den halt, also für den Integer braucht man halt nur, ja, je nachdem 32 oder 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 Dictionary verbraucht relativ viel Speicherplatz.
Wenn ich einen Eintrag in den Dictionary rein tue, dann hat es direkt 240 Byte Hauptspeicher verbraucht.
Das ist nicht ganz ohne.
Wenn ich sechs Einträge rein tue, 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 der 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 O von 1, jeder Zugriff.
Das heißt, jeder Zugriff dauert im Schnitt
gleich schnell.
Also amortisiert bedeutet für Dictionaries der gleichen Länge.
Nee, das bedeutet im Schnitt.
Im Schnitt amortisiert.
Im Durchschnitt bedeutet es, jeder Zugriff braucht ungefähr gleich lang und das ist eine konstante Zahl.
Es gibt einzelne, die dauern ein bisschen länger.
Diesen Worttransfer von amortisiert auf dem Schnitt hinbekommen.
Wenn du
eine große Anzahl Zugriffe machst, dann ist die Dauer so, als ob du
alles okay, genau, weil das Umbauen quasi Grenzwert 0 hat.
Das Umbauen passiert selten genug.
Genau, dass es der Grenzwert 0 hat in der Bitte erteilt und O von 1.
Also O von 1 bedeutet, es ist ein Problem.
O von 1 schreiben.
Also wenn ich ein Element einfüge, dann dauert das O von 1 und wenn ich ein Element rauslese, dauert das 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 Ofen 1.
Also das heißt tatsächlich, also um nochmal einhören, das so ein bisschen näher zu bringen, dieser Zeitnotation Big O noch nicht so viel anfangen kann.
O von 1 bedeutet, es dauert quasi keine Zeit, das zu tun.
Es dauert immer gleich lang.
Es ändert sich nicht mit der Menge der, also normalerweise, wenn du jetzt sagen, O von 1 im Vergleich zu O von N, ist jetzt bedeutet, dass sozusagen, wenn deine, äh, deine Eingabedatenmenge halt nicht N ist, dann wenn du eine Hashmap hast, dann ist es halt immer noch O von N immer noch konstant.
Genau, aber das ist.
Bei was anderes, bei einer Liste ist es halt O von N, wenn du darauf zugreifen willst, weil du musst ja alle Dinger angucken, ob es das jetzt ist, was du wolltest, haben wolltest oder nicht.
Aber O von 1 bedeutet halt, ich kann halt nichts machen.
Also es ist halt so.
Genau.
Das heißt, also auch egal, ob kleine oder große Datenmengen völlig wurscht, was da passiert.
Und das halt quasi in meiner Berechnung, ob ich da irgendwas algorithmisch verbessern kann zu vernachlässigen, weil das keine Rolle spielt, ob 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 einfach quasi, du hast einfach quasi die Keys mit Brackets dann gesetzt in einer Schleife oder was?
Genau, ja.
Genau, und hab einfach die Zahlen von 1 bis 10.000 als Key und als Value, das spielt ja keine Rolle, ja, wenn die nur die Größe wissen wollen.
Das ist dann ein sehr unnützes Dictionary, weil das halt einfach immer 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 Listen, eine Liste aus zwei Tupeln zusammengebaut.
Und dann in diese 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 eins?
Nein.
Dann das zweite Element, ist das eins?
Nein.
Und das muss ich dann 99 mal machen und beim 100.
sage ich, ist das Element 100.
Und dann sage ich ja und dann bin ich fertig.
Bei einem Dictionary, Hash Map, wir sprechen gleich, wie das funktioniert.
Im Moment, Magie.
Dann passieren halt zehn Rechenschritte und dann steht da, okay, du hast dir zu 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 halt eigentlich halt ein 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 und einfach dann nachgucken, wenn die Hashtable sind, diese Datentypen oder sowas, ja, genau.
Und dann halt überlegen sich irgendwie einen 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 musst
du nicht sagen.
Genau, aber ja, genau.
Die Liste an sich garantiert dir das nicht.
Garantiert dir nur, das sind Elemente in einer Abfolge.
Die nächste Frage wäre jetzt, wie halt in das Dikt, was ja auch im Prinzip eine Liste von Keys ist, jetzt erstmal so in der Synth, 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.
In die man dann halt reintritt.
Ich möchte noch dazu sagen, ja.
Ich möchte noch dazu sagen, du hast jetzt gesagt, das ist eine Liste von Keys.
Das ist so, 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 sie reingeschrieben wurden sind, liest sie nicht.
Ja, das ist die Reihenfolge, die jetzt halt irgendwann dazukommen sind, aber sagen wir mal, wenn wir ein Dikt von Python 3.4 nehmen, dann hat es keine Reihenfolge.
Also in Python 3.5 kam ein Order-Dickt.
Nee, also ein Order-Dickt gab es schon immer, aber
Standard, die Pets.
Dass das sortiert ist, es 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.
Okay.
Aber wenn man sich so ein ursprüngliches Dikt mal anschaut, dann sind die Keys eigentlich ein Set.
Die haben keine Reihenfolge in dem Sinne und die kann auch keine Duplikate enthalten.
Und das ist genau das, was eine Menge ausmacht, ja,
ein Set.
Hatte quasi ein Set auf 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 Dictionary 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 das kann man ja nicht.
Genau, damit kann man ja quasi auch über so ein Dictionary iterieren oder sowas.
Dann kannst du halt erstmal mit Mode.notated aufrufen und dann kannst du quasi for Key Value in Dick Dot Items, bla.
Genau, for Key Value in Dict-Items.
Das ist so ein Muster, das sieht man ganz häufig, weil man da einfach 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.
Naja, sagen wir so, wenn du das kostet Ausführungszeit.
Wenn du da eine Vorschleife machst über alle, dann ist das halt schon O von N sozusagen.
Ja, genau.
Nur im Einzelfall halt nicht.
Aber die Value nochmal rauszuholen, wenn du Key schon hast.
Genau, also die O-Notation von for Key Value in Dict Items 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 Disdictionary rein muss.
Natürlich nur für einen konstanten Faktor.
Ja, aber der Summe zählt halt auch auf.
Aber konstante Faktoren, ja, konstante Faktoren sind.
Also wenn etwas nur zehnmal langsamer ist, das ist auch ein konstanter Faktor, das
macht schon einen Unterschied.
Ist schon ein Unterschied, ja.
Genau.
Wie kann man denn dicks bauen?
Wisst ihr das?
Es gibt, ich habe vorhin einen ganz coolen Trick gelernt.
Es gibt ja mehrere Wege, Dictionaries zu bauen.
Ja, was meint ihr?
Syntaxmäßig jetzt geschreifte Kammer.
Also du kannst es natürlich einmal machen als Dictionary Comprehension, indem du sagst, geschweifte Klammer, Key Value, fortgeschrittener Stuff.
Oder du machst halt einfach die Definition einfach in den eckigen Klammern, schreibst dann eine Key in die Value hinter.
Oder du schreibst eine Liste von Keys und Values mit Gleichzeichen dahinter und machst dann ein Dick draus.
Also Dikt-Off.
Ja genau, das ist der normale, also das ist der Konstruktoransatz.
Du kannst die Keys auch in einer Schleife einfach hinzufügen oder hinzufügen.
Ja, genau hinzufügen.
Du kannst auch irgendwie, du kannst an durch halt Tupel-Unpacking oder sowas, die ganzen direkte reingeben mit so Sternchen, Sternchen, Halbparksyntax.
Beziehungsweise wenn du eine Sequenz von Tupeln reingibst von zwei Tupeln, dann nimmt
er die automatisch.
Eine Methode, die ich gerne verwende, ist Dikt.fromKeys.
Was macht das?
Naja, du gibt es 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-Methodenaufruf von dem Dikt.
Default-Dikt gibt es noch irgendwie, ne?
Das heißt, was anderes.
Da müssen wir nachher 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.
Diese Dictionary Comprehension ist eine der coolsten Wege, die es gibt, so ein Dictionary zu bauen, weil das 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 nicht so gut.
Nee, macht nicht so viel Sinn, dann muss man sich angucken.
Da 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 Dikt-Zip.
Also wenn ich eine Liste von Keys habe und eine Liste von Values.
Dann kannst du die zippen und dann machen die zippen und dann einen Dictionary draus machen.
Das geht auch nur für gleich lange Listen, ne?
Das geht nur.
Zip nimmt auch unterschiedlich lange Listen.
Naja, 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 das
Dictionary drin.
Einmal Reisabschluss, bitte.
Netter Trick.
So, wie kann man denn da Sachen wieder rauskriegen?
Dominik, weißt du?
Ich frag dich jetzt ab, ich finde es total gut.
Was meinst du?
Wie komme ich an die Werte wieder drin?
Ja, du kannst einfach den.
Wenn ich jetzt einen Telefonbuch habe, wie kriege ich deine Telefonnummer raus?
Du machst halt zum Beispiel entweder ein Get oder halt mit der Bracket-Syntax ziehst du einen Key-Saint-Serie.
Wie ist das da der Unterschied?
Bei Get kriegst du einen Default-Wert zurück und du kriegst einen Error, wenn du da rausversuchst, ein Key zu lesen, den es nicht gibt.
Genau, wenn du es mit eckigen Klammern machst, kriegst du im besten Fall einen Key-Error.
Genau.
Der heißt tatsächlich Key Error.
Also wenn man das abfangen möchte, gibt es
das heißt.
Genau.
Also und beim Get kannst du halt an den Default dann dranhängen.
Es gibt noch zwei andere coole Attribute.
Ich kann die Frage beantworten, ja.
Es gibt noch zwei andere coole Attribute, die heißen Pop und Pop-Item.
Und die sind quasi destruktiv, die sind destruktiver Zugriff.
Genau.
Wie aus der Liste, Punkt Pop entfernt Dominik,
dann heißt es, entferne den Eintrag für Dominik, 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.
Ich muss bei Pop muss ich immer den Key sagen, bei einer Liste müsste ich den Index sagen.
Genau.
Also er gibt dir den ersten Wert, was natürlich beim Dick nicht geht, weil das nur einer hat.
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 Pop-Item.
Und Pop-Item, das macht LIFO, last in, first out.
Das heißt, es gibt dir tatsächlich den letzten Eintrag, der hinzugefügt wurde, zurück als Item.
Das ist natürlich interessant.
Da kann man bescheiden.
Also Key und Value.
Das ist schon sehr cool.
Das heißt, du kannst so eine Wild-Schleife machen und kannst dieses Dictionary sozusagen abarbeiten.
Ja.
Und hast dann so eine Art Dictionary Keue.
Und das ist eine praktische Sache, die ich erst heute gelesen habe.
Ja, sehr schön.
Ne, habe ich auch so noch nicht verwendet, aber da fallen mir auch direkt viele Sachen zu ein, die man damit coolerweise cool machen kann.
Ja.
Wo man so ein Dictionary zerlegen kann.
Ja.
Ja, man, also es gibt noch, ähm, es gibt auch noch Set-Default.
Das ist, ähm, ich weiß nicht, ob man das Leute überhaupt erzählen sollte, dass es die Methode noch gibt.
Das darf man nicht sagen.
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, fällt mir schon ein, das ist vielleicht keine gute Idee.
Es ist, glaube ich, besser, da direkt ein Default-Dikt zu hören.
Ja, genau.
Das ist auch die Empfehlung, sollte man halt heutzutage eher Default-Dickt.
Oder Get.
Ein Get und dann den Wert setzen.
Wo ist denn das?
Get und Wert setzen und Default-Dickt.
Dafür müssen wir erst wissen, was ein Default-Dickt ist.
Dann erzähl mir, was ein Default-Dikt ist.
Ein Default-Dickt ist ein Dictionary, eine Unterklasse von Dictionary.
Das keine Keys hat, aber wenn du einen Key abrufen willst, den es noch nicht gibt, dann gibt dir den Default-Wert zurück.
Genau.
Du sagst ihm, welchen Standardwert es haben soll und wenn du einen Key abrufst, den es noch nicht gibt, kriegst du den Standardwert.
Oh, es gibt drei große Varianten davon.
Die erste ist die Lambda-Variante, wo du halt eine Funktion reingibst, die dann diesen Standardwert erzeugt.
Und das ist sozusagen die allgemeine, ja.
Das ist Default-Dickt.
Du musst dem Default-Dikt irgendeine sogenannte Factory geben, damit er diesen Wert erzeugen kann.
Und da kannst du jede beliebige Funktion reintun, meistens ist das halt irgendeine kleine Lehrerinderation.
Aber es gibt schon zwei Funktionen, die du da verwenden kannst, nämlich List und Int, die nützlich sind.
Also wenn du ein Default-Dikt Klammer auf Listklammer zumachst, dann heißt das, das ist ein Dictionary und wenn du deinen 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 Default-Dikt Int hast, dann kannst du jeden beliebigen Key abrufen und kriegst 0 zurück.
Du kannst einen Counter machen, dass du immer halt get auf hast.
Ja, aber Counter gibt es auch.
Da gibt es so eine Klasse für, ja.
Und die ist richtig cool, diese Counter-Klasse.
Die müssen wir jetzt auch gleich noch.
Das müssen wir auch klar noch besprechen.
Okay, wofür würde ich Default Dikt verwenden?
Das klassische Beispiel ist, wenn man sich so einen Counter baut.
Aber wenn dann nochmal, wenn du das gleiche, nochmal auch muss, gibt man natürlich dann den neuen Wert zurück, ne?
Genau, also wenn du einen Wert in dieses Dictionary, in dieses Default-Dikt reinspeicherst, dann ist es wie ein normales Dictionary, ja.
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 das ist nur so dieser Fallback.
Da ist nochmal noch eine Zwischenfrage, kleiner Expos.
Wenn ich jetzt da einen Get mache auf so eine Liste, ja, auf so einen Default-Dikt 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, gibt dir mir dann diese Liste, in der was drin ist.
Oh.
Warum nicht?
Das wäre das, was ich Jochen vorher gesagt hätte.
Das wäre Set Default.
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 doch schon gibt und dass das Objekt dieser Liste auf das dann ja.
Ja, aber die wird nicht in das Dictionary abgelegt.
Du musst
nicht tatsächlich zuweisen, die du nur das
in der Hand hast.
Und du musst die dann tatsächlich zugreifen zuweisen.
Wenn du das möchtest, dass du eine Liste abrufst und die dann bearbeiten kannst, dann musst du Set Default machen.
Und Set-Default heißt, ruf einen Key ab, wenn es denen 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 wäre das, was Default-Dickt so machen würde.
Okay, das heißt, dafür muss ich Set-Default machen.
Genau, dafür müsst ihr das Set-Dafault machen.
Ja, aber es ist die Funktion Set-Default, also sie ist in mehrerer Hinsicht verwirrend, sie ist auch verwirrend benannt, wie man jetzt auch gerade wieder sehen könnte.
Und vielleicht sollte man das echt mehr machen, weil tatsächlich, wenn man es aber Default Dikt macht, ist es sauberer.
Und ja, genau, was ich noch anmerken wollte zu den Factory-Funktionen, die man übergeben muss.
Also es kann eine beliebige Funktion sein.
Die einzige Bedingung ist, sie darf keine Argumente nehmen.
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, dann muss man halt da, das sieht dann komisch aus.
Das ist ein bisschen blöd, wenn es keine Argumente sein können.
Also Factories möchte man ja gerne mal auf eine bestimmte Art Weise initialisieren.
Das muss man ja irgendwie von einer Default-Factory alles schon erben und muss das dann irgendwie
curried sein.
Ja, aber da gibt es etwas, also zumal, wenn man jetzt bei unterschiedlichen Keys unterschiedliche Sachen machen möchte.
Es kann ja manchmal sein, dass 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-Dick ja alles so nicht mehr so richtig.
Eben deswegen, weil man kann halt nicht ein Argument angeben, was man dann.
Also das ist, das geht ja nicht mehr.
Da gibt es aber auch etwas sehr Cooles, was ich auch erst in der Vorbereitung, ich habe ja einfach nochmal geguckt, was zu dieser Episode habe ich mir nochmal so ein bisschen angeguckt, was habe ich denn an Literatur zu Dicts, steht da irgendwas Interessantes drin und habe 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 Danda Missing als sozusagen Spezialmethode, die man überschreiben kann, wo man dann den Key bekommt.
Das ist quasi der Key-Error.
Du kannst ja einen Key-Eror überschreiben.
Und macht dann Default-Tickt, mache ich dann eine neue Klasse, die von Default-Tickt erbt und überschreibt dann dann dann Missing und guckt dann mit einem Match-Case-Statement, was da drin ist.
Oder man kann, also du kannst von Default-Ticket erben, na klar, aber dann, also das musst du dann ja im Grunde nicht mehr.
Wenn du die Methode überschreibst, dann bestimmst du ja selber, was passiert.
Und da kannst du alles.
Das ging früher übrigens auch nicht.
Ich konnte früher nicht von dict erben, deshalb gibt es noch eine Klasse, die User-Dickt heißt.
Achso, das heißt
tatsächlich, ich mache tatsächlich sowas ähnliches wie User-Dict und ich mache eine neue Klasse auf die App einfach von Dict.
Und da überschreibe ich dann nur die Missing-Methode und dann gucke ich halt, was er statt dem Key-Error drauszugeben, dass er dann tatsächlich irgendwas Neues anstellt.
Ja, das würde auch tatsächlich funktionieren, aber es wird, diese Diskussion hatten wir in dem PDF, also Python-User Group Düsseldorf-Channel auch vor kurzem, ob es denn okay ist, von Dikt zu erben oder wenn man lieber von User-Dict erben soll oder so.
Und ich hatte das halt noch so im Hinterkopf, dass man von Userdikt erben soll und nicht von Dict.
Und tatsächlich habe ich jetzt auch nochmal nachgeguckt, und nee, man soll von Userdikt erben und nicht von dict.
Also man kann das ja zwar jetzt.
Warum?
Was ist da
der Unterschied?
Also der entscheidende Unterschied, warum das unter Umständen einem Problem machen kann, ist, dass bestimmte Methoden halt, also Missing ist jetzt, die funktioniert, die kann man überschreiben, aber bestimmte andere nicht.
Und wenn du dann dickt auf 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 Dikt, Dikt von dem Bild entdikt herbst und dann überschreibst du 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.
Also, und ja, das habe ich jetzt aber auch wieder vergessen.
Also es war auch irgendwie, es ist eine wichtige Geschichte, warum das, wenn das ein Data-Attribut ist und sozusagen die Zugriffe dahin nur delegiert werden, das macht auch irgendwie, ich glaube, es kann sogar sein, dass das der Grund ist, weshalb man Z-Item-Get-Item dann überhaupt quasi richtig überschreiben kann.
Ja, genau, genau.
Und daher sollte man, wenn man das selber, wenn man erben will und will Sachen überschreiben, dann lieber Userdikt nehmen, statt einfach vom Bild enterben.
Also, also User Dict
ist quasi eine Klasse, die das gleiche Interface hat wie Dictionary.
Ja.
Aber eben ein Attribut heißt, das heißt Data.
Und das ist ein Dictionary und einfach alles durchreicht an dieses Data.
Genau.
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.
Genau.
Ja.
Ja, okay, wusste ich auch nicht.
Ich wusste nicht, dass es da Unterschiede gibt.
Ja, es ist immer wieder interessant, auch wenn ich dachte, also ich meine, das verwendet man ja jeden Tag und irgendwie schon ganz lange und so.
Und dann muss man sich so, da kann ja eigentlich nichts Neues mehr, aber manchmal so.
Aber das ist was, was man doch relativ selten macht von Dictionary.
Also generell von Build-Ins, so Sachen fühlt sich immer so ein Stringpommel.
Ist nicht so häufig.
Die sind einfach gut genug.
Beziehungsweise, wenn man eine neue Datastruktur 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 Injector-Pettern oder sowas, dass man die halt dann beim Putz hat.
Genau, dieses Data, dass du halt sagst, 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.
Ja, das ist so meine Erfahrung.
Ich weiß nicht, wie ihr das seht.
Doch, doch, nee, ich sehe das, sehe das ganz genauso.
Achso, das ist, genau, das ist auch noch der eine der Grund dafür, warum das mit dem Delegieren eine gute Idee ist, weil halt ansonsten, wenn du direkt erbst, dann hat dein Objekt eine ganze Menge Methoden, die halt unsinnig sind unter Umständen.
Also in einem Kontext, wo man sich dann fragt, wenn man so dir macht auf dein Objekt.
Und dann sieht man halt einen ganzen Haufen komisches Zeug, wo man sich da 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.
Also wir müssen noch so ein paar Sachen, ich habe erstmal eine Notizenliste, ist gerade leider gerade leer gegangen, aber.
Da ist so ein Ladegerät und da ist ein, das kann man das ganze Telefon anschließen.
Oh, du hast USB-C?
Wow.
Nee, das ist sogar als Apple House halt USB-C.
Ja, ja, so braucht man das schon.
Cool.
Es gibt eine Methode, es gibt eine Methode in Dictionaries, 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.
Okay.
Und zwar ist der Pipe-Operator dazugekommen.
Ah, richtig.
Ja, klar, 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 man, dass jemand sowas brauchen könnte.
Das ist Dictionary-Vereinigung.
Ja, Unions zwischen Dikts.
Genau.
Dann 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 Sternstern und unter Dictionary 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 stimmt, ich wusste, dass das passiert ist.
Ich habe es aber nie verwendet, seitdem daher ist es mir jetzt gar nicht mehr bewusst, dass es alles gar nicht so gut ist.
Ein Update ist halt Julian.
Ist es exklusiv, ist die Frage.
Es ist immer exklusiv, weil du ja keine Keys
verdoppelt hast.
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, doch.
Dictionary Punktupdate übernimmt alle Keys und Values aus dem Update-Book-System.
Genau, aber die, die es noch nicht drin waren, was da drin ist.
Genau, aber wenn welche vorher schon drin waren und die dann überschrieben werden.
Genau, aber wenn die vorher schon drin werden, die sind.
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 Unit-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 des Jungs-Dicks.
Du hast D1 und D2.
Genau, das sind zwei einigermaßen des Dinge Dicts.
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 Dikt-Update.
Wenn du aber die Union machst, erstes Ding, das zweite Mann.
Nein, dann sind nur noch die zwei Keys drin.
Nee, das kann ich.
Nee, das wäre ja komisch.
Das wäre ja der Schnitt, nicht die Beinigung.
Achso, stimmt.
Ein Schnitt kann es nicht.
Gibt es nicht auch den Schnitt?
Das gibt es nur bei Set.
Bei Set gibt es das UNT-Apparator.
Gibt es nicht auch die Intersector?
Set.Intersect.
Ne, für Dickness gibt es keine Intersector.
Okay, schade eigentlich.
Weil das wäre doch eigentlich sehr logisch, dass das mit dem.
Es wäre logisch, dass es diese ganzen mathematischen Operationen alle für Set und
Diktator sind.
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 dickt und dann hast du die Unions direkt.
Das wäre doch schön Syntax schwer.
Ich probiere
das mal in der Odel aus.
Ja, mach mal.
Union ist oder
und das ist einfach die Vereinigung.
Also 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, Fitter.
Nee, das geht nicht.
Ne, und und geht schon mal gar nicht.
Die Python sowieso nicht.
Und und geht nicht.
Dann sagt er Unsupported Operant Type.
Bitwise geht auch nicht, oder?
Ja, okay.
Also tatsächlich, es geht nur um die Vereinigung, ja.
Ja, okay.
Wohingegen bei Set, wenn man das jetzt so macht?
Bei Set
gibt es Intersect.
Es gibt Set.intersect, es gibt Z.U.
Union und es gibt Z.
Es gibt noch eine dritte, Difference.
Symmetric Difference oder sowas, ja, genau.
Ja, Symmetric Difference ist ja das Minus, das andere Plus, das andere Minus das ein.
Oh mein Gott, dass er Intersect nicht hat.
Warum hat er das denn?
Also bei Set, dass bei Set geht, aber bei Dix nicht.
Das müsste ja irgendwann mal reinkommen.
Die Frage ist, was soll denn, wie sollen denn dann die Values aussehen bei einer Intersection der Keys?
Welche nimmst du denn dann?
Jetzt hast du mich.
Eine Liste von beiden wahrscheinlich oder sowas.
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, was man.
Also, ja,
eigentlich müsstest du den Schnitt über die Keys machen und dann entscheiden, aus welcher Quelle du
dir 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 aber, 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 Atolls oder sowas?
Also was diese, ja, oh, es gibt auch noch NemedTuple ist.
Ja, genau, named Tupel.
Das ist auch spannend.
Warum denn Nameduple?
Ja, das ist ein total komischer Name dafür.
Ich weiß auch nicht.
Um Dot-Notate-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.
Du hast auch irgendwie.
Und da ist genau ein Wert dazu drin.
Du hast so ein Konstruktor und irgendwie noch.
Ja, gut, aber das ist ja, da muss man.
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, ich meine, es ist ja auch so, dass wir nicht so gut.
Genau, genau.
Also in Python-Ojekte, das sind halt Dikts, sozusagen, was ihre Struktur angeht, ja.
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, als Skriptsprache, quasi Skriptsprache.
Vielleicht schon.
Da ist das auch, also bei JavaScript, da heißen die Dinger sogar Object.
Vielleicht ist das das entscheidende Merkmal.
Ja, vielleicht, ich weiß nicht.
Eine Skriptsprache.
Also bei Perl war das auf jeden Fall auch so.
Da waren auch, also ich meine, das hat ja keine Offenheit.
Bei dynamischen Klassen und dynamischen Instanzen geht es ja quasi nicht anders.
Du musst ja quasi diese Zuordnung haben von Attributname zu irgendeinem Wert.
Aber bei kompilierten Sprachen ist das ja anders.
Nee, da ist das 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.
Man kann das in Python auch machen, quasi.
Man kann das halt festdengeln, ohne dass es halt dann noch so dynamisch ist.
Ja, man kann halt die Attribute in einem Spezialattribut Dunder-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?
Nee, nee, das ist dann tatsächlich schneller.
Wenn ich auch weniger.
Wenn ich das mache, dann ist es, kann ich doch trotzdem zusätzlich machen.
Nochmal Dunler-Slots.
Achso, Moment, kann ich dann trotzdem dynamisch zuweisen?
Ich weiß es nicht.
Ich meine, das geht dann nicht mehr.
Das muss ich ausprobieren.
Joch macht seinen Editor an.
Einer von uns beiden ist vielleicht falsch.
Oder eben Nametuple.
Nameduple 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 Hybridsache.
So ein bisschen ist das Dictionary ja der Kern von Python.
Es gibt ja so eine Listen.
Moment, Moment.
Ich habe es gerade ausprobiert.
Nein, wenn man halt Slots definiert hat und dann was anderes dynamisch zuweisen möchte, kriegt man einen Exception-Attribute-Error.
Aber 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 Nametuple macht das doch genauso, oder Jochen?
Jetzt ist es auch schneller als eine allgemeine Klasse.
Ja, ja, klar.
Nametuple 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 in Zuordnung gemerkt wird von Index auf irgendeinen Namen.
Aber das wäre ja schon, das würde ja schon nichts bringen, sondern das würde ja, dann hörst du ja den gleichen Aufruf auf, 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 habe, dann ist 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 Nametuple, 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 Nametupel, auch gerade zum ersten Mal gefallen, eigentlich gesagt.
Achso, Slots, wie gesagt, darüber weiß ich jetzt gerne.
Ich hast du dicksfragen.
Ich dachte einfach, was ich.
Kl's mal als Nametuple.
Was ist denn ein Nametuple?
Ich wollte gerade nach Slots fragen, ja.
Ja, ja, das kommt gleich.
Naja, da definierst du sozusagen ein Objekt dadurch, dass du am Anfang, du gibst halt so, glaube ich, wie ist der Aufruf Nametuple, dann sagt man irgendwie einen Namen dafür und dann sagt man die Parameter, die Attribute, die das haben kann, irgendwie.
Und das verhält sich dann aber wie eine Klasse.
Ja, genau.
Und dann kann man mit Punkt drauf zugreifen, ja.
Aber nur mit diesen, die ich da angegeben habe.
Also wenn ich ein Nametuple habe, das heißt Fuba.
Keine Ahnung, das heißt Fubar und das hat die Attribute A, B und C.
Dann kann ich einen Fubar.a machen und Fubar.b und Fubar.c und kriege die entsprechenden.
Das verhält sich dann wie ein Dictionary, ja, für diese drei Keys.
Aber Dick kann ich ja nicht mit Dot machen, muss ja mit den Key Kategorien.
Genau, genau.
Also das ist wie eine Klasse.
Wie eine Instanz von einer Klasse.
Also das ist so ein Ding, das mache ich häufig ja, dass ich einfach eine Klasse mache, die heißt Dataholder und die hat keine Attribute, weil dann kann ich nämlich mit Punkten irgendwas machen.
Wenn wir jetzt gerade schon bei Nametupels noch sind, da gibt es übrigens auch eine kleine Neuerung, weil früher gab es ja immer vom Collections NameTuple, man muss ja NameTuple oft machen.
Und jetzt gibt es aber auch Typing Nametuple und Typing-NamTuple ist ein bisschen eleganter, weil dann kannst du einfach das wie eine Klasse schreiben.
Und dann darunter die Attribute.
Ich würde Nametuple 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 nicht.
Aber eigentlich, was man.
Dann erklärt auch mal Slots.
Wie auch immer.
Wenn man Nametuple verstanden hat, dann ist Slots leicht zu erklären, weil Slots ist nämlich eine andere Syntax für die gleiche Funktionalität.
Ja, 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 drinstecken kann.
Nicht eine Methode, nein, nein, das ist ein Attribut.
Das ist ein Attribut A, okay, das ist ein Attribut und da sind eine Liste von Namen rein.
Und das eine Liste ist und in der Liste stehen quasi die Strings drin von den Namen, die als Attribut einer eben erlaubt sind.
Wäre dann die Klasse, die Klasse hieße Fuba und die hätte ein Attribut, das hieß dann das Slots und da steht drin A, B und C als Strings.
Stehen da auch Methodennamen drin oder nur Attributnamen?
Nee, nur die Attributnamen.
Und wenn ich da Methodennamen reintreibe, dann kann ich da eine Methode für definieren, die trotzdem funktioniert?
Kannst du machen, klar, wenn du willst.
Da müssen wir ausprobieren, was passiert.
Kann sein, dass komische
Sachen passieren.
Nee, 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 es wie eine Methode, weil Methoden an Klassen sind nichts anderes als Methoden, die den Parameter self haben.
Aber was ist denn, wenn das nicht in den Slots drinsteht?
Ja, wenn es
nicht in den Slots drinsteht, kannst du nicht drauf zugreifen.
Genau, also 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.
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.
Ach, Slots wird zusammengebaut aus dem, was in dem Attribut-Slots drinsteht und in den Namen, die eigentlich Methode gibt.
Da wäre ich mir nicht so sicher.
Probier's mal aussachen.
Ja, ist meiner Meinung nach so.
Jetzt müssen wir gerade ein bisschen tippen und wir gucken, ob du
das jetzt gerade gleich.
Okay.
Also foo.
Das funktioniert schon mal.
Also genau so.
Und jetzt sagen wir mal foo.slots und das glaube nicht, dass das zusammengebaut wird.
Ich glaube, dass Slots bleibt so, wie es ist.
Ja, es bleibt
wie es ist.
Aber das funktioniert.
Methoden gehen, ohne dass in Slots drinsteht und es ist nicht in den Slots drin.
Ja, du kannst aber Methoden hinzuschauen.
Genau.
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 dann eine normale Klasse.
Okay, das 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 x gleich 10 reinschreiben und das kannst du auch auslesen.
Und du kannst das auch an der Klasse verändern.
Ja, okay.
Aber nicht in den Instanzen.
Weil in den Instanzen darfst du nur auf Slots zugreifen.
Und das bedeutet, dass eine Klasse mit Slots im Wesentlichen wie ein Nametuple ist.
Nur besser.
Mit besserer Syntax und mehr Methoden.
Und das ist auch der Grund, warum Nametuple nicht mehr so richtig.
Jawohl, aber ich finde, das ist das neue NameTuple, von dem Vertryping ist doch gar nicht so schlecht.
Nee, also es hat auch noch andere Nachteile.
Also es gibt ja jetzt auch denn etwas, was man vielleicht, ja, neben, also vielleicht meintest du das auch.
Es gibt ja Data-Classes, die sind ja auch jetzt in der Sprache drin direkt.
Genau.
Und die sind auch in eigentlichen, also es gab es auch, ich weiß nicht, Artikel zu, 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 Data Classes und nicht mehr nehmen Tuppel, weil Data Classes ist es schneller, es ist besser, es ist in jeder Hinsicht besser, es gibt keinen Grund mehr dazu nehmen.
Das alte Zeug ist nur noch drin.
Ja.
Okay, ja.
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 Data Classes ist halt dieses Atres-Modul, das sehr beliebt ist.
Das kann halt dann noch viel mehr.
Und das ist auch relativ schnell, wenn ich das so richtig verstehe.
Ist auch sehr nett, ja.
Und also das ist das, was vielleicht damit angefangen hat.
Dann Data Classes 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 Data ist das nicht schneller als Atis.
Ich weiß nicht, nee, Paydentic meine ich auch, ist eine eigene Geschichte.
Ja, Pydentic ist eigen, aber es ist nicht schneller.
Doch, doch.
Nee, ist es nicht.
Nee.
Es ist ein Einstehender sogar langsamer als Atis zum Beispiel.
Okay.
Ich dachte, es wäre Data-Clein drin.
Ich habe irgendwo so ein Video, das muss ich eigentlich bei den Shownos verlinken, wo jemand das ganz gut auseinandernimmt, wo der so am Timings auf mir macht.
Also das muss sich mal irgendjemand mal ganz genau angucken und dann Bescheid sagen, wie das denn wirklich ist.
Und dass wir alle
in dieser 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 Nametuple ist halt das, was man am wenigsten nehmen sollte von den ganzen Sachen.
Ich finde ja die moderne Sundheitresse sieht eigentlich ganz hübsch aus.
Es ist halt so schnell.
Wenn du es halt aufschreiben willst, vom Typ-Import Name-Toupel, dann machst du einfach auf, keine Ahnung, Name-Tupel, Define-Nametup und irgendwas und dann schreibst du halt die Attribute untereinander wie in der Klasse.
Definierst ihn jetzt klar, welchen Datentyp haben die denn und so, das sieht schon so aus, als.
Okay, vielleicht muss ich mir das auch nochmal angucken, weil dass 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 denn an der Implementierung da was geändert hat, aber die glaubst du wenigstens haben, oder?
Also das muss ich erstmal kurz aufmachen, um das mal anzuschauen.
Tatsächlich.
Okay, dann muss ich da mal ein bisschen.
Ja, wenn man die Sicht
habe, ich würde tatsächlich eher Data Classes verwenden für diesen Use Case, aber ich habe ja immer seltsame Ansichten.
Ich habe mich von der Funden, dass ich nicht im Standard bin.
Ach, so sieht das.
Nee, okay.
Ach doch, so sieht das aus, ja, okay.
Ja, typing.named tuppel und dann sagt man hier irgendwie quasi.
Ja, aber das hast du sogar noch, Moment, jetzt muss ich uns.
Ja, da unten, also das nicht, sobald ich
zuhälere den Monitor nicht
sehen können.
Genau, das ist das Problem bei Podcasts.
Ja, und das Problem ist auch, weil ich kann das jetzt nicht vorlesen, kann ich schon, hilft nur nicht.
Ja, genau, aber das ist meistens alle, ich finde so Gesundheit, das sieht doch gar nicht so
schlecht aus.
Ja, okay, also gut.
Das ist halt ein klasse.
Also es ist auch eine Möglichkeit, die man machen kann.
Ja, ja, ja.
Ja.
Ja, ja, sehr nett.
Okay, aber das ist ja nur syntaktischer Zucker, oder?
Wenn ich das jetzt richtig mache.
Ja, Syntaktikschucker.
Ja.
Okay, gut.
Also dann ist es quasi ein Name-Douple.
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 einen Default-Dict oder macht einen Get und inkrementiert die Zahl dann und so weiter.
Einfach ein Counter und die Sequence reintun und fertig.
Und man kriegt ein Dictionary raus mit den Ansatz.
Super, ist großartig.
Und das hat auch diese ganzen Funktionen, die man dazu braucht, ja.
Also wenn man das dann updaten möchte oder wenn man das Generator hat oder wenn man irgendwas anderes in der Hand hat, ja, 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.
Es deckt so viele von diesen Fällen ab, für die man sonst default dickt verwendet.
Ich habe noch was anderes Schönes gefunden und zwar heißt es Chainmap.
Das ist auch im Collections Modul drin.
Was ist denn eine Chainmap?
Eine Chainmap, das ist so ein.
Mich 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 er 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 das 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 immer ins Oberste rein.
Ja, ich überlege gerade auch, also ich meine, das ist auch so was, ja, ich weiß es nicht genau, ich würde es jetzt nicht, aber es ist halt eine, ich mache jetzt auch so ein bisschen JavaScript gerade.
Und was dann doch ein bisschen einfacher hinzuschreiben ist als in Python, ist halt diese Dreipunkt-Spread-Operator-Syntax, wo dann halt sich neue Sachen generiert, indem man halt 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 erfasst man.
Sache.
JavaScript ist die halt der Kern von JavaScript.
Jedes Objekt oder jedes Dictionary in JavaScript hätte einen Prototypen, auf den du zurückfallen kannst.
Und das kannst du hier mit Chainmap nachbauen.
Ja.
Ja, nett.
Fand ich sehr schön, dass es gibt.
Habe ich noch nie gebraucht.
Wüsste ich jetzt auch nicht, an welcher Stelle ich das einsetzen will, aber gibt es auf jeden Fall.
Und ich glaube, wenn man das braucht, ist das eine sehr, sehr nützliche Sache.
Weil man so Hierarchien damit bauen kann.
Ja.
Vielleicht nochmal einmal ganz kurz, weil ich gerade nachgeguckt hatte zu diesem Which Python Data Classes Best, habe ich einen Artikel, also ein Video gefunden von einem Kanal, der M-Coding heißt.
Und da vergleicht jemand tatsächlich Data Classes, Name Tuple, Tupel Address und Pydentic nach Geschwindigkeit und Memory FG und so.
Und da scheint Pydentic vor allem beim Erstellen von den Objekten relativ schlecht ab.
Okay, gut, ja.
Und dass irgendwie, weiß ich nicht, 15 Mal so lange dauert oder so.
Aber sonst vielleicht schnell.
Ja, gut.
Im Laufe seines Programmierebens hat er mich davon weg entfernt, Geschwindigkeit
primär zu machen.
Und Notiztitel wieder angemacht.
Ja, ja, genau.
Geschwindigkeit, ja, ist die Frage, braucht man das oder auch will man das?
Das ist völlig egal, haben wir nicht genug Rautspeicher und sind solche, also das überhaupt nicht mehr.
Nie genügend Geschwindigkeit und nie genügend.
Letztens jemand kennt ihr bestimmt auch.
Pavel Meier aus Chaos Radio oder jetzt.
Aus dem Chaosumfeld, nee, die kenne ich alle nicht.
Ah, okay, der.
Naja, gut.
Der hatte das mal irgendwie so beschrieben, dass sein Computer eigentlich für ihn nur eine relevante Eigenschaft, also ein Attribut hat, das irgendwie wichtig ist.
Oder das drei gibt drei ganz wichtige.
Und zwar, das ist halt erstens Performance.
Das zweite ist halt Performance.
Und das dritte ist, was auch noch sehr wichtig ist, Performance.
Es sind ja nur drei Dinge.
Ja, da ist auch schon was dran.
Aber tatsächlich, naja, irgendwie sowas wie Lesbarkeit und so ist auch nicht so schlecht.
Es hast du der Papel Meier, der dieses mega langsame Covid-Dashboard geschrieben hat.
Ja.
Genau.
Tassel.
Es gibt so Leute, also ich meine, es gibt auch Felder, in denen das wichtig ist, ja, 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 es schneller macht.
Ich sehe mir sehr gerne die Videos von Casey Muratori an.
Der kommt halt aus der Spieleentwicklung und der sagt, man kann den C alles machen, also soll es 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 der da gerade benutzt und dann die die Befehle, den Befehlssatz kennen, weil dann kannst du nämlich alles 256 Mal so schnell machen wie vorher.
Und ja, das ist prinzipiell korrekt.
Aber vielleicht ist SMB-Coden auch zu langsam, also wenn man es gut kann, ich weiß nicht.
Der kann das sicherlich gut genug, aber.
Noch kurz zu Fabrival.
Ah ja, genau, da gibt es auch gerade auf Netflix so eine so eine Miniserie oder so: The Billion Dollar Code, die ist quasi mehr so, orientiert sich an deren Biografien da.
Ja, im Fernsehen.
Ich habe schon eine Wiederwerbung Jochen, das ist aber eine werbungsvolle Folge.
Diesmal ist ja noch gar nicht so, also ja, da, also gut, wir machen Werbung, Werbung machen wir immer, aber wir werden nicht dafür bezahlt, dass
Netflix, weil sie zuhört, der Jochen wäre durchaus offen dafür, bezahlt zu werden.
Also Johannes, wir können jetzt ja nicht mit anderen Werbepartnern direkt parallel Netflix würde ich vielleicht auch nicht.
Also wir hatten ja letztes Mal, also wenn wir jetzt schon das Thema Werbung haben und jetzt gerade Werbung versuchen, machen wir.
Ja, wir haben ja überlegt, ob wir Werbung schalten sollen und ein bisschen darüber lustig gemacht und wir haben ein bisschen Feedback bekommen.
Leute sagen, ja, macht doch einfach.
Ja, dann haben wir uns auch gedacht, ja okay,
dann machen wir halt
so ein bisschen kostendeckend arbeiten oder so.
Es ist Leute, die euch bezahlen, ist ja verrückt.
Und die noch nicht berührt und schockiert.
Du wirst nicht bezahlt, Hannes macht ja gar keine Diskussion.
Achso, ja gut, dann
ist der egal.
Nicht so direkt, aber ich finde, das wäre natürlich so eine Sache, die man machen könnte.
Man könnte also einmal Hosting-Kosten, so die anfallen, ein bisschen damit vielleicht bezahlen.
Aber was man auch machen könnte, wir könnten dem Johannes ordentliches Audio-Equipment schenken zum Beispiel.
Ja, da müssen wir nochmal drum mal sehen.
Dann ist das jetzt hier mit der Spendenaufruf, wenn die Zuhörer gerne möchten, dass ihr mich besser hören könnt, dann folgende Bitcoin-Adresse.
Wir schalten 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 und dann würde ich ja einfach gar nicht mehr, ich wäre dann einfach gar nicht mehr hier, sondern ihr würdet Gäste.
Vielleicht könnte man sich dann noch andere Hosts leisten, die das so etwas professioneller machen und sowieso eine andere Webseite, die auch nicht so stärker aussieht.
Und dann könnten wir endlich, was könnten wir denn dann eigentlich machen?
Ich wollte mir ein Schloss kaufen.
Wenn wir den Strand zur Ruhe setzen
und mal eure Hobbys verfolgen, vielleicht, keine Ahnung.
Vielleicht machen wir einen Pass auf.
Naja.
Ich habe schon gesagt, also ich warte immer noch auf mein Schloss.
Möchtest du auch einen Spendenaufruf starten?
Also mein Spendenaufruf war für ein gescheites Mikrofon, Dominik Spendenaufruf ist für ein Schloss.
Ja, für meinen Schloss, für mein Schloss.
Ja, ja, für seinen Schluss.
Ja, okay.
In diesen ganzen anderthalb Stunden, wo wir jetzt schon zusammensitzen, haben wir jetzt tatsächlich noch gar nicht drüber gesprochen, was eine Hashmap überhaupt ist.
Du hast jetzt schon vorher vergessen, wir gebraucht haben, unser Audio-Equipment vorzubereiten, obwohl wir alle vorher sind.
Ja, das ist halt an meinem schlechten Mikrofon, aber.
Trotzdem sind wir noch nicht so weit gekommen zu erklären, was überhaupt eine Hash Map ist und wie sie funktioniert.
Ja, stimmt.
Also 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 kann man direkt weiß man direkt, wo es sein muss, weil das irgendwie.
Ja, der Trick ist, der Trick ist im Wesentlichen schon im Namen, ja.
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 Hashes, 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, dann kriege ich im Wesentlichen einen zufälligen Wert in der Menge aller möglichen Hashes raus.
Und wenn ich diesen Hash jetzt mit Modulo nehme, ja, und quasi als Index in eine Liste reinnehme, dann bedeutet das, dass der irgendwo hin zeigt.
An einen Index, der nicht vorhersehbar ist und der auch gleich verteilt ist über die gesamte Reichweite der Liste.
Aber ich muss da reingehen, quasi die Länge der Liste, das heißt, ich weiß, wie groß das maximal ist.
Genau, ich muss wissen, wie groß die Liste ist.
Beziehungsweise Python macht da viele coole Tricks, die Magie helfen.
Aber das ist bei einer Hashmap immer so, die hat so einen Befüllungsgrad, wir haben es vorhin schon angesprochen, bei Python ist es 2 Drittel, die ist maximal zwei Drittel voll.
Also Wurzel 3, hast du gesagt?
Wurzel 3 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 das Wurzel 3?
Und der heißt auch 4.
Wurzel 3 ist 1,7 knapp dann.
Vielleicht noch besser einzeln.
Ist übrigens auch interessant, weil ternäre Logik wäre besser, weil das näher an irgendeiner Zahl dran ist.
Ach, keine Ahnung, spielt keine Rolle jetzt.
Das Wichtige ist, wenn ich aus einem Dictionary 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 in eine Hash Map etwas reinschreiben möchte, dann mache ich den Hash aus diesem Key und schreibe den Wert in diese Liste an der Stelle des Hash-Index rein.
Und das ist sozusagen der Trick.
Ich berechne einen, ich nenne es mal, 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 zwei Hashes zu dem auf den gleichen, also 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 herrschen, 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.
Ein Hash vom Hash.
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 Map einfach nur in eine Richtung wächst.
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 zusammen dampfe, dann sind sie immer noch gleich verteilt und das ist der Trick daran.
Bedeutet halt, dass der Key hashable sein muss.
Es gibt eine ähnliche Datenstruktur, die heißt Tree Map.
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, ja, dann habe ich Zugriffe in die alle Login sind.
Genau, das Default, ich weiß nicht, ob es immer noch so ist, die Hash-Map, Default-Implementation der Standard-C<unk>-Bibliothek irgendwie vom Boost war irgendwie so ein Tree Map.
Und hat dann irgendwie, als wenn man was optimieren wollte, dann C<unk> geschrieben hat und dann war das überraschend von der Performance selber.
Das war da hinterher langsamer als die Ding zum Fall.
Großartig.
In Java gibt es diese beiden Optionen unter diesen Namen.
Es gibt HashMap und es gibt TreeMap.
Das heißt, bei Java muss man sich immer raussuchen, was man haben möchte.
Okay.
Die Antwort ist immer HashMap, aber egal.
Und natürlich bei einer Hash Map heißt das, dass man immer Hash-Funktionen haben muss.
Und Hash-Funktionen sind auch so eine Sache, ja.
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 dann verwendet?
Das weiß ich nicht.
Nein.
Also ich denke dir.
Ja, das weiß ich nicht.
Ja, es gibt ja so Hash-Funktionen, die kennt man, ja.
Es gibt MD5 und CHAW 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 Einsatzigen 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.
Ja, also ich kenne die Hash-Funktion für kleine Integers und die ist ja einfach.
Ah, die ist das Integer seitlich.
Also der Hash von 1 ist eins.
Hash von 2 ist 2.
Aber das wird dann, wenn die Zahlen größer werden, ist das dann nicht
mehr so.
Von 128, ja.
Das glaube ich auch immer noch 128.
Ah, ich glaube, es geht nur bis 127.
Moment, Moment, ich habe doch hier die REPL schon aufgemacht, da kann ich auch gleich nochmal Hash 128.
Ich habe ja kürzlich einen 27, aber wenn ich 512.
Verdoppeln war eine gute Strategie, habt ihr eben gesagt.
512 ist auch immer noch 512, bei 1024 auch immer noch, oh mein Gott, was sind.
Beintegers einfach immer so.
65 oder 100.
Nein, nein, nein, wenn die wirklich groß werden, dann ist es nicht mehr so.
Okay, sie müssen wirklich groß werden.
Ich bin gerade schon bei einer Million, bei der Milliarde.
Dann sind es vermutlich 32 Bitend, ne?
Über 32 Bitness.
Signed.
Unsigned end.
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 hinten dran machen.
Ich weiß gar nicht mehr, wie das heißt.
Das sind die, die früher L hießen.
Das ist auch super.
Erstmal beim Verdoppeln, also 128, 12.000, 24, dann 10.000, 100.000, eine Million, 10 Millionen, 100 Millionen, dann auf einmal so.
Ich weiß nicht, wie die Zahlen heißt jetzt da draufgefallen 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 irgendwie maximal mehr
60 Bit.
Aber wo Zeit Implementation D-Tay sind, das eigentlich Signed oder Unsigned Ints in Python?
Und was ist das ins?
64 oder ins?
Designed 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.
Also 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.
Was ist denn Hash von Material?
Aber das ist ja nur ein Implementationsdetail, das ist nur ein Umsetzungsdetail.
Hash von minus 1 ist minus 2.
Minus 1 ist minus 2, ja, schön.
Interessant, okay.
Wir haben wieder was gelernt.
Gut, 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.
Hash minus 2.
Minus 4.
Nein, keine Ahnung.
Oh, Hash-1 ist gleich Hash-2.
Da ist es.
Da hast du direkt eine Kollision.
Dann musst du Open Addressing machen.
Ja.
Ja, okay.
Ja, witzig, witzig.
Das heißt, kann man dickt keys, wenn das Int sein können, können das auch negative Int sein?
Ja.
Na klar.
Okay, das heißt erscheinen.
Alles, was Hash will.
Du kannst nochmal das,
was ich nicht verändern kann.
Das heißt, er macht tatsächlich, wenn du minus 1 reinschreibst, dann muss er tatsächlich eine Kollision machen und minus 2, dann muss er quasi eine Ebene tiefer gehen und ja, okay.
Du kannst auch deine eigenen Objekte.
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, aber nein, das geht.
Das ist okay.
Du solltest denn eigentlich auch immer noch Frozen-Versionen machen oder an die.
Musst du dann eine Methode an deine Klasse dran machen, die hashable ist?
Ja, also es muss natürlich hashable sein.
Du hast hier jetzt einfach Danda Hash.
Danda Hash.
Dann wird die aufgerufen und dann kannst du eine, wenn du eine ID schon hast, dann kannst du die natürlich auch zurückgeben.
Oder du kannst halt, ja, irgendwie, wie auch man willst du.
Jedes Objekt ist doch hashable, oder?
Gerne.
Die Objektidentität als Hash-Funktion.
Ja, das kann natürlich sein, dass das der Default ist.
Wie könnte man das jetzt schnell rausfinden?
Help, dann Hash.
Wie wäre das denn?
Genau, aber du kannst natürlich deine eigene Hashes machen.
Scheint so zu sein, ja.
Help, dann 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 einem Dictionary nicht ändern dürfen.
Das heißt, wenn ich ein Objekt, 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 dann natürlich aufpassen.
Aber ich meine, oft hat man ja tatsächlich eine ID, die man nehmen kann.
Und man gibt halt bei der Hash-Printhol, 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, ja.
Dass du halt irgendeinen Wegbildest, was du dann hashst.
Und klar, das kann man natürlich machen.
In meiner Erfahrung tripp es nicht so häufig auf, aber wenn du sagst doch, dass du das gerne machst, dann.
Vielleicht mache ich es auch falsch.
Ich weiß nicht so genau.
Also ja, gerade mit Zusammenhang mit Data Classes, beziehungsweise so Atris, da benutze ich.
Data Classes sind ja automatisch hashable, oder?
Naja, bei Data Class, das weiß ich gar nicht so genau.
Also ich habe das jetzt, was ich jetzt im Kopf habe, ist mit Attres.
Und da muss man dann auch, da kann man dann auch solche Sachen sagen.
Also einmal man kann es natürlich selber implementieren, aber man kann auch sagen, irgendwie, also ich habe, das soll hashable sein und diese Attribute will ich dafür verwenden und die müssen dann auch natürlich auch Dread-Oni sein und so.
Ja.
Und dann macht es manchmal Sinn, weil dann kann man halt bestimmte Sachen lookupen mit einem anderen bestimmten Ding.
Und dann, das ist 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 er 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 wirklich schneller.
Also wenn man das braucht, ist das schon ein Superpower.
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.
Also ja, was ich ganz gerne vielleicht noch sagen wollen würde oder so, ist halt, dass man auch selber sich Sachen implementieren kann, die dann halt so funktionieren wie Dikts.
Also es gibt ja seit Python 3.3, glaube ich, Protocols oder weiß nicht wie das.
Man hat halt auf jeden Fall diese Abstract-Base Classes, wo es dann Interfaces für diese ganzen Geschichten gibt.
Und dann da hat man dann halt.
Aber Moment, also Protokolls sind fertige ABCs Abstract-Base-Klasses.
Die Implementierung von Python-Modulen, die es schon gibt.
Ach, cool.
Die kann man ja auch fürs Typing da benutzen.
Ah, ja, genau.
Und die sind großartig fürs Typing.
Da kann man nämlich richtig gutes Duck-Typing machen, was aber trotzdem getypt ist.
Ist großartig.
Genau.
Und dann kannst du eben deine eigene 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 Dick benutzen würdest und so.
Das kannst du auch sehr coole Sachen mitmachen.
Wobei das Protokoll von einem Dick-Train ist ja vergleichsweise groß.
Was ist das denn?
Was ist denn ein Ding?
Das meine ich Mappable, aber.
Ich gucke mal gerade, wo haben wir das denn da?
Es gibt Mapping.
Mapping heißt das genau.
Ein Mapping.
Mutual Mapping.
So, äh, ach, jetzt steht das Interface hier aber nicht dabei.
Vom Collections.abC Import.
Abstract Base Class.
Moment, ich importiere das gerade mal mach mal in dir.
Ja, das ist cool, weil dann kannst du einfach von Mapping ergen lassen und alles, was du nicht implementiert hast, wird dann einfach direkt gerased.
Wenn das halt nicht da ist.
Das ist doch schon deine Zungen.
Typechecker sagt dir da auch direkt, dass das.
Ja, ja, genau.
Du hast direkt gezwungen, das richtig zu implementieren.
ABC Boot Collections.
Ja, ich habe mich richtig.
Weil ABC ist ja die ABC selber interessiert.
Ich weiß,
ich weiß.
Gleichzeitig reden, tippen und das alles.
Ich glaube, was du aber auch Podcast hast, wo wir nicht mehr so gut haben.
Mach mal ein neues Objekt vom Mapping auf einfach.
Ich glaube, das kannst du nicht interessieren.
Das sehen Sie nächstes Mal in diesem Podcast.
Das geht nicht.
Genau, da steht aber jetzt schon, was du brauchst.
Ja, okay.
Ich muss halt GetItem, Itter und Längen definieren von meinem Mapping.
Okay, zumindest.
Also das Interface selber ist jetzt doch was größer als halt 37 Methoden und das ist natürlich schon eine ganze Menge.
Ja, das hatten wir ja vorhin auch schon angesprochen, dass eben Dicks relativ viel Oberfläche haben.
Weil sie halt für alles verwendet werden.
Ja, aber eben, also man kann das halt verwenden.
Interessant, interessant.
Ist das euer Lieblingsdatentyp?
Ja, also von den primitiven Dingen auf jeden Fall.
Ich habe das auch letzte, also diese ganzen Typins-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 ja manchmal so.
Wie alt bist du gleich noch?
Jungen Hüpfer.
Ja, ich, äh, sie sind noch älter als ich.
Die im Kopf Alpen und Säcke.
Ja.
Nee, also verdiente Veteranen, 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.
Die ganze Scheiß,
gar nicht mehr.
Pythonic.
Genau, und so ein bisschen kann ich das natürlich auch nachvollziehen, muss ich, muss ich sagen, also zum Beispiel, äh nehmen wir mal, 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 Python Essential Reference, glaube ich.
War lange super.
Jetzt gibt es da sogar Python Distilt, 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, 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 irgendwie, wenn einer sich mit Java hingesetzt hat und hat dann irgendwie so angefangen, erstmal Interfaces zu definieren und dann irgendwie, keine Ahnung, sich erstmal in ja, weiß ich nicht, in so ein Spinnennetz aus komischen Dingen, die man alle so machen muss, weil man sie halt machen muss, hinschreibt, genau, Getter Setter, diese ganzen Zeugs.
Und dann hat man sich in so einem Spinnennetz von Dingen verheddert, bevor man auch nur eine Zeile produktiven Code geschrieben hat.
Und dann ist man mit den Dicts und den List-Comprehensions schon lange fertig.
Und damit hat er nicht so ganz Unrecht.
Also tatsächlich ist es so, dass Dicts, wenn man das beherrscht und so wirklich verstanden hat, wie das funktioniert, mit eben vielleicht noch Dikt-Comprehensions, vielleicht noch Generator-Expressions, würde ich dazu nehmen, und List-Comprehensions.
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 dann halt dem Python-Prinzip gar nicht jeder.
Simple Platter sind Complex wieder.
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 einfach immer Annie sagen.
Jeder Typ ist Annie in TypeScript.
Aber in C Sharp, in C Sharp kannst du es auch machen, kannst du auch Annie sagen, aber wird nicht gerne gesehen.
Also meine ist talentet Annie übrigens, der sagt, das reicht ihm nicht.
Ja, okay, gut.
Das ist halt eine Einstellungssache.
Das kannst du abschneiden.
Ja, kann auch.
Es 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 ein Dictionary verwenden, aber kann ich an der Stelle nicht.
Ich muss nicht so viele Spieleprogrammieren, aber muss aber auch zwölf Umwege machen.
Ich sehe aber auch, also ich sehe auch den Vorteil von diesen Typing an.
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 da diesen klassischen Kampf zwischen Explore und Exploit.
Wo jeder entscheiden muss, was er machen muss, um ein Problem zu lösen.
Also Explore als unbekannte Dinge angucken und Exploit als 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 es mit dem Alter eher zu Exploit geht als zu Explore, was ja auch okay ist, ja, weil du 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.
Einige Hacker schon von Anfang an Greise im Kopf gewesen, ja.
Ja, das ist.
Sorry.
Man muss sich das auch manchmal wieder zurück in den Kopf rufen, dass man vielleicht gelegentlich wieder Explor machen muss.
Das ist auch der Grund, warum ich sie Sharp und Tarpskyp und so weiter mache, damit man mal ein bisschen wieder was anderes macht.
Ich dachte, dass sie Sharp macht, damit du endlich noch ein Spiel releasen kannst.
Ja, irgendwie muss man ja sein Schloss sicher arbeiten.
Erschlossen arbeiten.
Das heißt, man widerspricht sich dort schon von alleine.
Ja, Erben, ich glaube, das
wird bei mir schwierig.
Oder erobern.
Schlösser müssen eigentlich geobert werden mit Verteidiganlagen oder Heirat.
Ja, das ist auch eine Art der Eroberung.
Ja, eine
gewisse Art.
Sieht bei mir jetzt alles nicht so gut aus.
Ich bin schon verheiratet.
Und mit Erben, ich habe meinen Vater gefragt, aber im Inventar.
Du hast halt die hübsche genommen, ist eine schlechte Teilung.
Absolut.
Und hübsch und schlau, das sind ja schon zwei Eigenschaften, die man sonst nicht im Paket kriegt.
Ich habe meinen Vater
gefragt, von Bannf, was Erb hatte direkt die Schlösser austauschen lassen.
Ja, aber das ist eben, man muss sich auch mal 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 da 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 die ist das Mandat What if everything was a pointer?
Und in Java ist What if everything was an object?
Under 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 haben wir so ein bisschen verherrlich, wir haben jetzt noch gar nicht die Nachteile davon erklärt, warum will man das denn vielleicht nicht benutzen?
Nachteile ist, was könnte es jetzt noch für Nachteile geben?
Es ist O von 1, es kann alles speichern, es ist großartig.
Also vielleicht so wie Speicherverbrauch.
Ja, ja gut, das haben wir am Anfang schon gesagt.
Also ein Dictionaryverbraucht direkt ein Viertelkilobyte.
Das heißt, bei solch embedded Programming oder irgendwelche so IoT-Sachen ist es dann vielleicht nicht die richtige Wahl.
Es ist auf jeden Fall relativ wastev.
Also man hat immer einen großen Overhead.
Immer mindestens.
Wie laufen alle auch für Kisten, wo wir genug Speicher haben, dann 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.
Speicher.
Wenn du 1000 TPS machen kannst, statt einer Million und du brauchst aber eine Million, dann wird das halt schon irgendwann relevant.
Ja, Moore's Law wird alles gut machen, langfristig.
Auch eine Waschmaschine bekommt dann mehrere Gigabyte Speicher für einzelnen Waschprogramme und den Stück.
Die Maschinen haben ja heutzutage schon mehr Wahl.
Irgendwann musst du da einfach mal noch so Grundrohstoffe reinkippen, wie, keine Ahnung, weißt du nicht, Sand und Salz oder sowas.
Und da baut es automatisch Waschmittel raus und das perfekt für die Wäsche geeignet ist.
Wäschern die einzelnen Wäsche sind.
Du kannst doch schon so Waschmaschinen, Waschmittel-Cartridges kaufen.
Und die werden dann auch so dosiert, dass es für den Waschmittelhersteller optimal ist.
Okay, okay.
Für den Waschmittelhersteller ist es natürlich.
Ja, ich hoffe, euch hat eure Folge, unsere Folge zu Dicts heute gefallen.
Falls dir noch irgendwas dazu einfällt, dann kann ich das nicht so ein bisschen.
Ja, ich glaube, Pix und sowas machen wir einfach mal wann anders ist jetzt.
Ja, ich glaube, wir sind jetzt heute weit fortgeschritten.
Also mein Lieblingsmodul in Python ist ja build-ins.dikt.
Das ist mein Pick der Woche.
Okay.
Ja, ich mache dann einfach von einem Patentik dort dickt.
Ja, okay, perfekt.
Und Jochen macht Name-Tube.
Ja, Atris, ja, eher.
From Jochen Imports.
Die eigene Implementierung, ja.
Aber genau, kann man sich auf jeden Fall auch mal angucken.
Das lohnt sich.
Sie haben doch Pics gemacht.
Da haben wir doch welche gemacht.
Ja, gut.
Ging schnell.
Ging schnell.
Ja, dann bleibt uns gebogen.
Hörst du uns immer, wo ihr uns hören wollt.
Und eine schöne Zeit.
Und bis zum nächsten Mal.
Nächstes Mal.
Genau.
Bis zum nächsten Mal.
Tschüss.