Transkript: Fragen über Fragen
Vollständiges Transkript der Episode. Zeitstempel beziehen sich auf die Audiowiedergabe.
Ja, hallo liebe Hörerinnen und Hörer.
Willkommen beim Python Podcast in der 15.
Episode.
Hier ist der Dominik bei mir sehr Jochen.
Wir sind wieder im Wintergarten.
Hallo.
Es ist sogar diesmal scheint sogar noch die Sonne, ist der Wahnsinn.
Ja, es ist auch selten, dass wir aufnehmen, wenn es noch hell ist, aber heute.
Ja, wir haben tatsächlich Dezember irgendwie.
Ja, der 12.
Dezember, genau.
Vielleicht kann ich so schlecht, wenn wir das mal dazu sagen, wann das ist.
Ja, wir haben uns ein bisschen Zeit gelassen in letzter Zeit in den Folgen.
Es war so viel zu tun, aber wir versprechen, wir werden es nicht aufgeben und euch weiter damit bespaßen können.
Ich wollte ja nicht belästigen sagen.
Das ist aber die Frage, was man da empfindet, wenn man das heute.
Unsere Folge heute soll wirklich mal so eine Anfängerfolge sein.
Ja, wir möchten mit euch heute reden über ein, zwei Fragen, die wir stellen möchten, was für Anfänger für Fragen haben oder was mir eingefallen ist oder was einige Hörer uns geschrieben haben.
Worum es eigentlich bei Python geht?
Ein paar ganz grundlegende Sachen.
Vielleicht wird es ja spannend.
Also, ja, keine Lava-Folge, kennt ihr schon.
Wen ihr schon gehört habt.
Ja, ja.
Genau.
Mit den Themen können wir auch irgendwann mehr klassen, machen einfach mal nur die nächste Lava-Folge, ja.
Ja, was machen wir hier eigentlich heute Wochen?
Und was ist so passiert in der Szene?
Und gibt es irgendwas Neues?
Nee, nicht, dass ich glaube, seit dem letzten Mal hat sich da gar nicht so viel getan.
Django 3 ist raus.
Oh, ja, doch, ja, richtig, du hast recht.
Ja, tatsächlich, Django 3 ist raus und das war das natürlich eine tolle Geschichte.
Ich habe das direkt mal versucht zu installieren und da so ein paar Sachen irgendwie mitzumachen, aber hab dann feststellen müssen, dass ein Haufen der Abhängigkeiten, die man so defaultmäßig irgendwie in Django-Projekten drin hat, dann nicht mehr so richtig funktioniert haben, beziehungsweise dazu führen, dass man dann halt ein Traceback kriegt, wenn man was mit den Entwicklungsserver zu starten.
Und ja, unter anderem sowas wie Django Model-Utils, was irgendwie fast alle Leute verwenden, oder also ich verwende es eigentlich immer, wahrscheinlich auch eine Menge andere Leute wegen Timestamp-Model oder sowas man ja oft verwendet.
Und ich weiß nicht mehr genau, was es noch alles war.
Es waren, ich habe dann für die, ich, die Sachen, die nicht funktioniert haben, da habe ich dann einfach die geforgt auf GitHub und hab das dann versucht zu fixen und dann halt eben entsprechend immer Pull-Requests aufgemacht.
Das heißt, ihr könntet bei Jochen in den Repos, die versuchen, die auch bei Dango 3 funktionieren.
Nein, nee, das sollte man vielleicht nicht machen.
Da sieht das Gate 10 oder so.
Nee, nee, nee, nee.
Aber es hat mich gewundert, wie viel da noch nicht funktioniert hat.
Also es waren bei so einem normalen, ich weiß nicht bei welchem ich das probiert habe, entweder bei einer Webseite oder auch bei der Python Podcast-Projekt-Dings habe ich mal versucht, das auf Django 3 umzustellen und das ist mit fünf Abhängigkeiten oder so sind kaputt gegangen und da habe ich, ich glaube, ich habe auch so fünf Pull-Requests irgendwie gemacht.
Dann gibt es irgendwie immer drei Versionen oder vier Versionen, ne?
Dann hier drei.
Also 0, 1 und 2 und dann ist nämlich ein Major Release.
War es das nochmal was?
Ich glaube, null ist immer so die neue Feature-Sachen.
Nee, ist mal gerade ungerade.
Gerade sind immer die Long-Term.
Ne, ich glaube, zwei ist Long-Term.
Punkt zwei.
Also 2.2, 1.2, 3.2 sind die Long-Term.
Achso, ja, kann ich mal nochmal nachgucken.
Ich weiß nicht so nur.
Bin mir sicher.
Okay, gut, sehr gut.
Und eins ist irgendwas anderes, das weiß ich nicht.
Aber ja, deswegen habe ich mich nur gefragt, also was man dann macht, also für Security-Patches dann wahrscheinlich immer die Zweier-Version nehmen, dass man irgendwie stabil sein möchte irgendwie.
Nee, also das, was tatsächlich empfohlen wird, eigentlich, also das ist auch so eine Legacy-Geschichte, das mit den Long-Term-Support-Geschichten.
Und naja, jedenfalls sagt das, derjenige, der aktuell irgendwie da ja auch hauptberuflich fürs Django-Projekt arbeitet, Carlton Gibson, dass man, dass er empfehlen würde, und das machen eigentlich alle Leute, die da wirklich viel Ahnung von haben, dass man halt, also früher war das wohl mal anders, aber mittlerweile sind die neueren Versionen von Django so stabil und so gut getestet, dass man eigentlich immer möglichst nah dran an der Entwicklung bleiben sollte.
Weil es auch gar nicht mehr so schlimm ist, bis dahin abzudaten.
Es geht gar nicht mehr so viel kaputt.
Sollte eigentlich nicht.
Wir haben gerade gesehen, genau, diese ganzen Testes hier.
Also eigentlich, weil das halt macht halt viele andere Sachen deutlich einfacher, wenn man das so rummacht.
Und wenn man halt auf der Long-Term-Support-Version sitzt, dann hat man halt irgendwann ein großes Problem und das will man vielleicht dann doch nicht.
Also die Art, wie man das heute macht, aber auf der anderen Seite machen das viele Leute schon seit langer Zeit so.
Insofern kann man, die kann man auch nicht einfach alle so vor den Kopf stoßen.
Aber so wie man das heute eigentlich machen sollte, ist eigentlich immer die aktuellste Django-Version verwenden.
Ja.
Okay.
Und ich versuche das auch immer und normalerweise funktioniert, also bis jetzt, auf die Zweier-Serie hat das eigentlich sehr gut funktioniert, bis jetzt Umstieg auf 3, da hat es halt nicht mehr funktioniert.
Und das war auch in allen Fällen das gleiche Problem.
Und zwar sind halt so ein paar private APIs für die Unterstützung von so alten Python 2-Geschichten, sind jetzt aus Django 3 rausgeflogen.
Also eigentlich gibt es ja keinen Python 2-Support mehr, auch seit Django 2 schon nicht mehr.
Oh, das läuft ja aus, die haben ja jetzt noch, können ja runterzählen, jetzt sind noch Tage.
Es sind nur noch Tage, bis es irgendwie vorbei ist.
18, 19.
Ja.
Und aber es waren noch so ein paar Geschichten dabei, so zum Beispiel, man konnte irgendwas, es gab so einen Dekorator Pi 2 Unicode Stringen oder sowas, den man über Funktionen setzen konnte und dann kam das halt mit auch den alten Geschichten klar und Six gab es halt auch in Django drin, was aber Six ist.
Ja, auch so eine Geschichte, die einem helfen soll, damit umzugehen, wenn es halt Python 2 und Python 3-Geschichten sind.
Wir haben eigentlich versprochen, dass eine Anfängerfolge sein sollte.
Ja, okay.
Und der Antwort ganz sicher in die Materie reinzugehen.
Es ist eigentlich auch nicht so richtig.
Also es sind ein paar Hilfsfunktionen, die einem dabei helfen, das für 2 und 3, Python 2 und 3 gleichzeitig zu machen.
Die sind jetzt tatsächlich entfernt worden.
Die waren vorher bloß deprecated, aber jetzt sind sie halt wirklich weg.
Und das heißt, wenn jemand die noch verwendet oder ein Paket die noch verwendet, dann gibt es halt ein Traceback an der Stelle.
Also alles, was jetzt in Python 3 deprecated angezeigt wird, ist bei Python 4 dann weg.
Äh, bei Python, sage ich schon, bei Django 3, 4, ja.
Ja, also diese Geschichte, diese Geschichten waren jetzt halt dann weg.
Ja, okay.
Und das hat, äh, hat dann auch diverse Pakete gebrochen.
Und insofern, ja, also Umstieg auf Django 3 nicht so super easy.
Wie lange ist jetzt Django 2 rauskam?
Wie lange das her ist?
Ich weiß es nicht mehr genau.
Ich würde mal so tippen.
Ages.
Ja, fast zwei Jahre oder so.
Irgendwas.
Um die zwei Jahre ein bisschen.
So, das geht ja.
Ja, also die Release-Zykel bei Django sind ja auch viel kürzer geworden.
Das war früher alles viel länger und ja, Django 2 gab es jetzt gar nicht so lange.
Ja, fällt mir noch welche News ein, weil sonst machen wir tatsächlich weiter mit Content heute.
Ja, nö, Content klingt gut.
Also ich stelle jetzt immer ein paar blöde Fragen.
Ja.
Und ich versuche dich dazu zu bringen, dass du die Frage möglichst kurz beantwortest.
Also so eine Minute pro Frage oder so.
Vielleicht schaffen wir das.
Wow, okay.
Ja, alles klar.
Ich weiß nicht, immer ganz einfach, bei einigen Themen ist das natürlich auch was anderes, aber mal gucken.
Ja, schauen wir einfach mal.
Also erste Frage, ist Python eine Schlange?
Ja, wo kommt der Name her?
Also, äh, nee, tatsächlich ist das eine Referenz auf Monty Python.
Spam, spam, spam, spam, spam, spam.
Genau, genau, und was auch interessant, der, der, also Monty Pythons Flying Circus, also das Flying Circus ist wiederum eine Anspielung auf, glaube ich, Ersten Weltkrieg, Roter Wohn irgendwie Geschichte, die nannte man halt, äh, das war halt so die informelle Bezeichnung, weil die halt immer mit Zelten auf irgendwelchen Äckern und Wiesen unterwegs waren, weil es sowas wie Flugflächse ja damals noch gar nicht gab, wurden die
dann halt auch mal der fliegende Zirkus genannt.
Und ja, ja, aber wo Monty Pyth eigentlich herkommt, was ich jetzt auch.
Also Guido hat halt das dann ja irgendwie so ausgedacht.
Genau, also die Referenz des Namens der Programmiersprache bezieht sich schon auf Monty Python.
Also ich finde dabei eine Schlange eigentlich wie cooler.
Und ich würde einfach sagen, ich nehme auch immer so eine Schlange als Symbol und es ist ja sogar im Logo mittlerweile drin.
Nee, klar.
Wenn ich mir ganz viele Pythonmuster auf meinen Körper tätowieren lasse, dann ist das natürlich ein Zeichen von meiner Liebe zur Sprache.
Tja, man kann sich ja schlecht nur irgendwelche Gags auf den Körper tätowieren lassen.
Das geht natürlich nicht.
Ich habe übrigens noch keine Tattoos.
Leider meine Frau sagt, ich darf nicht.
So.
So, so.
Tja, da muss man sich wohl entscheiden.
Die nächste Frage wäre, welche Einsatzzwecke von Python fallen dir ein?
Ja, schon eine ganze Menge, aber ich würde sagen, die allerwichtigsten zur Zeit sind Data Science ist jetzt, glaube ich, das am stärksten gehypte Thema momentan.
Immer noch, sogar.
Ja, doch, ich denke schon.
Einfach deswegen, weil das halt irgendwie alle machen wollen, weil da auch viele Fortschritte passieren und Python ist halt die Programmiersprache, mit der man das vielleicht am besten machen kann, abgesehen von R, aber R ist halt ein bisschen, hat ein bisschen einen engeren Einsatzzweck und du kannst halt nicht gut Webgeschichten zum Beispiel in A schreiben oder so.
Oder ganze komplette Systeme in A bauen, das geht eigentlich nicht gut.
Aber mit Python geht das, daher ist Python irgendwie da schon so, gerade für produktive Geschichten, das Mittel der Wahl.
Also wenn man jetzt nicht nur Sachen analysieren möchte oder explorative Analyse von irgendwas machen möchte, sondern möchte es tatsächlich einsetzen, dann kommt man eigentlich um Python nicht wirklich drum herum.
Es gibt ja auch noch so ein paar Leute, die dann irgendwie, oder sagen wir so, das ist auch ein großer Bereich, aber die dann Java oder so verwenden.
Es gibt ja auch irgendwie mit Skala, also nicht Java, sondern die Java M und die meisten verwenden die Leute dann irgendwie Skala obendrauf und Spark und da gibt es auch so Data Frames.
Aber ich würde sagen, das ist ein deutliches Stück kleiner als die Python, als der Py Data Stack.
Ja, also das ist auf jeden Fall das größte Thema, glaube ich, momentan, aber Webentwicklung ist nach wie vor auch sehr groß.
Dann eine Geschichte, die jetzt kommt irgendwie.
Ja, wollen wir auch unbedingt nochmal was zu machen.
Ist alles, was irgendwie so mit Home Automation-Zeugs zu tun hat.
Home Assistant ist ein großes Thema.
Ich habe da letztens um Weihnachten rum, dann kann man ja auch nochmal gucken, ob diese ganzen Geschichten noch gehen oder Geschenke in bestimmte Richtungen werfen, die irgendwas in der Art tun, weil das ja doch eine ganz angenehme Sache ist, wenn man halt Lampen und sowas automatisch steuern kann.
Das ist natürlich ganz spannend, weil man hat halt irgendwie ein ganz kleines Zubehör, das irgendwie, wenn ich das richtig mal verstehe, meistens so in C am besten programmiert ist.
Und man hat irgendwie so eine High-Level-API, so wie MicroPython oder sowas, die man da draufschmeißt und kann er einfach in Python auch die ganzen Module nehmen und
ja, also die ganzen Endgeräte, das ist ja halt die Frage.
Also man kann das, wenn das so was Arduino-mäßig ist, ist das auf C, was man da normalerweise schreibt, aber es gibt halt auch mittlerweile Chips, auf denen Mikro, auf denen man MicroPython installieren kann und dann kann man da einfach Python schreiben und die haben halt WLAN und ansonsten hast du ein Problem, wie kommunizierst du eigentlich mit Sensoren oder irgendwelchen Dingen, die dann was schalten oder so.
Wenn du da über irgendwie das über Funk, DVBT oder so machen muss, so ein bisschen ätzend und WLAN ist natürlich schon nicht so schlecht und das geht eigentlich alles mittlerweile.
Aber halt eben, ich glaube, der größte Punkt ist, dass halt Home Assistant ist halt in Python geschrieben und das ist halt das Ding, was zum Verwalten von diesem ganzen Kram halt üblicherweise so verwendet wird, wenn man jetzt nicht irgendeine fertige Lösung wie jetzt, na, wie heißt das denn, von Apple?
Ja, ich könnte ja jemanden, hast du nicht gesehen, oder?
Oder Google oder Amazon oder so, die haben natürlich ihre eigenen Geschichten.
Was ich da interessant, ich hatte letztens nochmal genau in dem Zusammenhang mir dieses State of the Union von Home Assistant den Talk angeguckt.
Und das war mir gar nicht so klar, dass die mittlerweile unter den Top Ten der Projekte bei GitHub sind, die am meisten Contributions kriegen.
Okay, cool.
Aber die werden am meisten gerne daran basteln, selber irgendwie so ein bisschen.
Ja, ich war überrascht, wie viel das ist, weil das ist ja jetzt eben noch nicht so prominent Also ich glaube, es waren sowieso sehr wenig Open-Source-Projekte in den ersten zehn.
Also da waren eher solche, das fand ich auch so ein bisschen erschreckend, aber das.
Wir haben noch keine Zeit.
Wir haben noch keine Zeit.
Aber sowas wie Visual Studio zum Beispiel, Visual VS VS Code oder so, ist in den Top Ten, TensorFlow und so, da sind ja alles nur so mehr oder weniger Open-Source-Projekte nicht so richtig eigentlich, ne?
Und aber Home Assistant schon.
Also ja, da geht auf jeden Fall auch noch was.
Und ansonsten, ja, alles, was irgendwie noch so an Serverinfrastrukturen automatisch hochziehen, Deployment, da ist Python auch sehr stark vertreten.
Das heißt, Web haben wir noch so ganz kurz gesagt, ich glaube gar nicht so, ist gar nicht so klein, oder?
Nee, Web ist auch sehr groß, ja.
Also gerade, also Django und Flash sind ungefähr beide gleich groß, mehr oder weniger.
Und es sind beides große große Bereiche, in denen sich passiert.
Viele der Top-Seiten sind irgendwie da irgendwie eins von beiden.
Also, genau, also ziemlich Allround-Sprache eigentlich, kann man sagen.
Ja, okay.
Da kann man fast alles mitmachen.
Was sollte man in Python können, um einen Job zu bekommen?
Das, äh, äh, ich weiß nicht, also ich glaube, da kann man, das ist immer ein bisschen schwer, ne, ne?
Wenn man das dann sagt, was die Leute da machen sollen, und dann sagt irgendwie die Library und das, was besonders interessant zur Zeit, dann braucht man irgendwie eine gewisse Zeit, um das zu lernen.
Wobei die meiste Zeit, die man braucht, um das zu lernen, wahrscheinlich dabei drauf geht, programmieren zu lernen.
Das dauert halt einfach lange.
Und dann ist es halt in dem Moment, wo man es gerade wieder veraltet.
Also insofern, das hilft alles nicht.
Aber ich würde sagen, tatsächlich die Geschichte, die am meisten bringt und von der aus man dann alle anderen Sachen tatsächlich leicht lernen kann, ist halt tatsächlich einfach richtig programmieren können.
Das ist schon so die Fähigkeit, die man haben sollte.
Oder das ist halt auch etwas, was nicht so, es ist ja ja.
Richtig programmieren können, das hört sich jetzt total einfach an.
Das hört sich total einfach an, aber das ist tatsächlich nicht so verbreitet, wie man sich das wünschen würde.
Also das kann man immer, man denkt immer so, ja, das macht man halt irgendwie oder da machen Leute irgendwie einen Kurs oder kaufen sich irgendwie, ich weiß nicht, ob es sowas überhaupt gibt, Python in 21 Tagen oder das geht nicht in 21 Tagen und das geht auch nicht in einem halben Jahr.
Das dauert alles ein bisschen länger.
Ja, manche Leute denken ja das, wenn sie den Syntax einmal gesehen haben, dann können wir das nicht mehr so gut.
Genau, dass sie das dann, dass das das gleiche wäre, aber das stimmt halt nicht.
Die Syntax ist ja auch bei Programmiersprachen eigentlich gar nicht so.
Also für Anfänger schon, die verstehen ja erstmal überhaupt nicht, was da steht.
Also der erste Schritt zum Verstehen, worum es überhaupt geht.
Ja, aber wenn man das eben mit einer natürlichen Sprache vergleicht, es gibt halt viel weniger Worte.
Es gibt halt ein paar, ja, es gibt ein paar Verben sozusagen oder Worte.
Hast du aber die ganze Standard-Library mitbedacht?
Klar, also die Libraries sind dann nochmal ein anderes Thema, aber das muss man ja auch alles gar nicht so unbedingt können.
Man muss halt, wenn man die Syntax und halt die paar Worte, die es tatsächlich gibt, kann, dann kann man das ja zumindest mal alles lesen.
Ja, also ja, das ist halt, also programmieren können ist aber so ein bisschen wie ein Musikinstrument können oder halt auch Fremdsprache lernen oder so, und das ist halt eine Geschichte, die dauert einfach.
Da gibt es dann halt auch Sachen, wie man das schneller hinkriegt und wie man das effektiver üben kann und so und wenn man das dann kann, dann kann man sich eigentlich in jedes Thema relativ schnell einarbeiten, würde ich jetzt mal so einfach sagen.
Und das ist halt auch, denke ich, also die entscheidende Geschichte, die man können sollte.
Sich in Themen schnell einarbeiten.
Ja, beziehungsweise halt.
Diese Geschichte, die halt lange dauert, halt schon vorher erledigt haben, weil das wird einem niemand gerne bezahlen, dass lange dauert.
Aber ich würde auch sagen, da gibt es halt enormes Potenzial.
Jetzt hört sich so ein bisschen an, das kann das ja jeder, aber das stimmt nicht so.
Also die allermeisten haben damit Probleme und strugglen da.
Und das ist nur nicht die Mehrheit aller Programmierer kann ordentlich programmieren, würde ich jetzt mal so sagen.
Ja, das musst du halt eigentlich noch definieren, was denn ordentlich.
Ja, das kann ich ehrlich gesagt gar nicht so genau.
Und ist auch die Frage, ob eigentlich ist es auch wieder so ein bisschen, ne, ich will eigentlich niemanden ausschließen.
Ich würde sagen, ja, selbst wenn man das nicht so total hundertprozentig kann, wahrscheinlich haben die meisten von uns auch schon irgendwie Jobs gemacht, wo sie dachten, dass sie dafür eigentlich gar nicht geeignet werden oder so.
Und das haben dann halt irgendwie gelernt, ja.
Ich meine, so ist das halt auch normal.
Das ist wahrscheinlich auch in anderen Bereichen so.
Und vielleicht muss man sich einfach mal trauen, irgendwas zu machen oder zu sagen, dass man irgendwas kann, obwohl man es halt vielleicht nur so ein bisschen kann und noch nicht so perfekt.
Ja.
Ja, aber du musst ja trotzdem damit rausrücken, was denn jetzt richtiges Programmieren dann überhaupt ist.
Also das ist ja zwar eigentlich jetzt nicht auf meiner Liste, aber dann musst du jetzt einen kleinen Kohfoto unterhalten, ich geb dir sogar zwei Minuten.
Naja, das wäre gar kein Problem, das sind zwei Minuten erklärt.
Also ich, ich würde sagen, wenn man halt keine nichts total, also wenn man Dinge so macht, wie sie gemacht werden sollten, nicht so total schrecklich Dinge falsch macht, vielleicht.
Weil tatsächlich ist es das, was man oft sieht, dass Sachen halt wirklich, also nicht nur so ein bisschen nicht ordentlich sind, sondern so Kleinigkeiten, sondern dass so Dinge so gar nicht richtig sind eigentlich.
Was gehört denn dazu?
Also was würde denn da?
Also ich würde sagen eben, dass der Umgang mit den ganz einfachen Datenstrukturen, ja, also irgendwie Listen, Dicts, irgendwie Skalare und damit halt ordentlich umgehen kann.
Also wenn man das schon kann, ist schon viel.
Hat man schon viel.
Weil das schon viele Leute nicht so richtig hinkriegen.
Und ja, dann halt, dass man eben Sachen halt ordentlich in Funktionen packt und nicht irgendwie Spaghetti gut schreibt, dass das halt alles so halbwegs sich nicht dauernd wiederholt.
Dry, don't forget yourself.
Ja, und die ganzen, aber da gehen wir fast schon in diese Detailgeschichten, oder dass man halt Tests schreibt und diese ganzen Best Practices verwendet und Versionskontrolle verwendet und so.
Mit den Daten, das muss man später nochmal sagen, da habe ich nochmal so ein paar Fragen.
Da müssen wir noch mal ein bisschen drauf eingehen, was denn überhaupt jetzt Skalar, Datentrum, was alles ist.
Okay, also du sagst halt einfach, okay, man muss halt die Prinzipien Best Practices irgendwie kennen und anwenden und sich daran so ein bisschen hochhangeln und irgendwie sich was besorgen, was man da.
Ja, und viel Code lesen, halt viel sich mal angucken, was man nicht.
Das Problem ist natürlich, wenn man jetzt jemanden liest, wo du sagtest, die Mehrheit der Programmierer ist gar nicht so hervorragend.
Und dann lese ich jetzt vor, wo
ich würde es vielleicht andersrum, ich würde sagen, da ist viel Verbesserungspotenzial.
Also man sich anguckt, was, wenn der Code, der geschrieben wird von Leuten oder der so in Firmen läuft oder so, ist das dann so, wie es sein könnte, oder kann da noch, geht da noch mehr?
Und da muss man sagen, da geht eigentlich fast immer noch deutlich mehr.
Ja gut, aber wenn man sich seinen eigenen Code anguckt, dann ein halbwegs später, dann denkt man natürlich schon so, oh, was ist das?
Genau.
Aber ja.
Ja, was erstmal, also ich habe noch eine Basisfrage bekommen vom Olli, die hatte noch geschrieben, Tipps für eine gute Syntax, also deine Top Five oder so.
Heutzutage würde ich sagen, Black verwenden und nicht mehr drüber nachdenken.
Also einfach Black, boom.
Vielleicht, also Namen vielleicht auch.
Namen sind natürlich eine ganz schwierige Sache.
Also wie kommt man da auf gute Namen?
Da muss man auch lange drüber nachdenken, oft.
Also ja, das gibt da gibt es ja auch den bekannten Witz, ne?
Was sind die zwei schwierigen Sachen?
Ja, in der Formatik irgendwie Dinge benennen, Caching und Off-by-One-Error Errors.
Ja, aber genau.
Also Dinge benennen ist schwierig, ist eine Kunst und ja, wo man sich da auch dran orientieren kann, ist so ein bisschen wie bei guten Kommentaren.
Man sollte eher darauf achten, hinzuschreiben, warum man das macht oder was das macht.
Nicht so sehr, wie da irgendwas passiert oder so.
Ja, und halt dabei, wenn man verschreibt, dran denken, dass das, wenn das jemand liest und dann halt verständlich sein sollte, weil Code viel öfter gelesen wird als geschrieben.
Ja.
Okay.
Was ist mit sowas wie List Comprehensions?
Würdest du das bevorzugen gegenüber klassischen Lu?
Nö, kommt drauf an.
Also ich würde sogar eher ein bisschen die andere, ich würde sagen, lieber eine Vorschleife verwenden und List Comprehension halt eher dann, wenn es halt irgendwas Einfaches ist, wo, ja, wenn es halt offensichtlich und einfach ist, dann kann man auch gerne List Comprehension verwenden.
Aber wenn man, also ich meine, auch da, auch da, das ist halt, wenn man irgendwas entdeckt, wie es funktioniert und das dann cool findet, dann fängt man an, das überall zu benutzen.
Und ich habe dann auch schon nicht List-Comprehensions gebaut, irgendwie, wo ich dann halt mehrfach verschachtelt irgendwie über Dinge iteriert habe.
Und das wird bei List-Comprehensions sehr, sehr schnell, sehr, sehr unübersichtlich, wo ich dann halt irgendwie stolz drauf war, so ein Statement hingekriegt zu haben, in einer Zeile, Code Call.
Nicht in einer Zeile, das geht dann halt nicht mehr in einer Zeile, aber dann so
drei Zeilen List
Comprehension irgendwie mit Bedingungen drin und verschachtelt und so lange getüftelt, bis es irgendwie ordentlich funktioniert hat, das macht ja dann auch irgendwie Spaß.
Das ist halt so ein bisschen wie Puzzeln.
Aber ich fürchte, wenn da jemand dann drauf guckt, der das verstehen muss und das unter einem gewissen Zeitdruck tut, dann würde der sich wahrscheinlich irgendwie das Remote Strangulation Protocol irgendwie zur Hilfe wünschen.
Das Remote?
Ja.
Ich weiß nicht, ähm, ja, das kennt wahrscheinlich auch keiner.
Damals gab es so einen Text auch schon lange her: Bessered Operator from Hell.
Und da gibt es die Sys-Admin, äh, also es gibt die Sys-Admin Man Pages oder die Sys Admin Recovery, gab es eine News Group und dann ASR, ne?
Alt Sys Admin Recovery, das war die News Group und dann gab es die ASR, Man Pages und Tools.
Ich glaube, wenn man Man ASR sagt oder Man Knife oder Man Snip oder so, dann kriegt man das auch noch irgendwie auf einem Linux zu sehen.
Da gibt es dann Tools, mit denen man irgendwie Usern die Attitude von Usern wieder reduzieren kann.
Und diese Tools sind halt sowas wie Snip oder Knife, ist so Axt.
Wo der Axt irgendwie mal dazwischen geht und Dinge gerade richtet.
Usern regulieren, das tut sich toll an.
Ja, das klingt eine Staatorganisation.
Das sieht man Spaß an, wenn man auf der richtigen Seite steht.
Ja, ist natürlich so ein bisschen, ich meine, das Mindset dahinter ist auch etwas fragwürdig, aber es ist damals irgendwie lustig.
Und eines der, da gab es auch Protokolle und eines der Protokolle in dem Zusammenhang ist halt das R S R R R STP, RS, äh, weiß nicht, eben Remote Strangulation Protocol, wenn man dann Leute über Fernverbindungen.
Sehr gut, sehr gut.
Ja, also das ist das, was man in Staatsorganisationen gerne hätte oder wo
man daran
arbeitet, das automatisiert zu bekommen, ja.
Also ihr braucht gute Admins für den Staat, damit das funktioniert.
Ja.
Ja, also okay, jetzt ein bisschen Syntax haben wir gemacht.
Also die Frage wäre jetzt noch, was gut, als du Python-Full Stack dann, also wenn man jetzt schon ganz viel kann und so, was würdest du sagen, wenn man richtig Full Stack entwickelt will?
Full Stack ja, das ist so ein Ding, was heutzutage auch wieder in aller Munde ist, wobei das auch selten tatsächlich so ist.
Würde ich sogar sagen, auch das, ich mache das nicht eigentlich.
Ich bin deutlich eher auf der Backend-Seite als auf der Frontend-Seite, aber Full Stack hieße ja, dass du quasi alles machen kannst, von unten bisher.
Also Full Stack in Python geht gar nicht, weil das geht
nicht wirklich.
Genau, weil mit Frontend bist du halt nicht, da brauchst du halt dann schon JavaScript für.
Und ja, oder es ginge theoretisch auch, aber das ist halt ein Bereich, der schön wäre, wenn das mit Python funktionieren würde.
Momentan geht das nicht richtig.
Also man konnte natürlich Python auch irgendwie Richtung WebAssembly kompilieren und dann halt im Frontend verwenden, aber es gibt keine, es gibt eben nicht so viel wie für JavaScript die ganzen UI-Bibliotheken, die man da so braucht, um halt Dinge irgendwie in Browser zu machen.
Also schwierig.
Ja, das heißt, JavaScript braucht ihr, wenn ihr Fulltech machen könnt.
Und wenn nur Python kriegt ihr das gar nicht so hin.
Aber vielleicht wollt ihr das ja auch gar nicht so machen, weil warum sollte man Fulltext machen, wenn man sich andere Sachen wie Data und Backend-Doot hat.
Naja, also wenn du eine Webseite machst, hast du halt sofort diesen ganzen Kram, wobei du da möglicherweise eben auch ohne JavaScript oder ohne viel JavaScript auskommen kannst.
So eine ganz stinknormale Webseite, so
ein bisschen CST machen oder sowas, ja.
Ja, auch
kein Python.
Es ist auch wieder kein Python, genau.
Aber das geht natürlich auch immer noch und ist eigentlich auch für viele Anwendungen irgendwie gar nicht so schlecht.
Aber ja.
Ja, gibt es ja so ein paar Frameworks, ne?
Crid, Material, Lies und so.
Naja, also ohne JavaScript.
Aber das ist ja was anderes.
Ja, Full Stack geht gar nicht, nur Python.
Ja, nicht so.
Und das ist tatsächlich auch einer der großen Risiken irgendwie für die Zukunft von Python, wenn das halt, wenn das eigentlich quasi so aus dem Web-Ding, weil die Frage ist jetzt, kommt Python nochmal ins Frontend oder geht JavaScript ins Backend?
Und wenn der Weg in die Zukunft so aussieht, dass wir dann JavaScript, weil das natürlich auch gewisse Vorteile bringt.
Du kannst Brossel dann schreibst einmal den Code, kannst ihn im Backend und im Frontend verwenden.
Wenn wir jetzt auch im Backend zunehmen, JavaScript kriegen, dann brauchst du halt eigentlich Python in der Webendwicklung gar nicht mehr.
Oder es läuft umgekehrt.
Und wir kriegen auch irgendwann einen Python im Frontend, das wäre natürlich eigentlich die schönere Variante.
Ja, da müssen wir mal dran arbeiten, dass das passiert.
Das ist nicht eine gute Sache.
Ich glaube, also die Chance ist gar nicht so schlecht.
Also ich glaube, Python ist noch bei Anfängern gerade ein bisschen beliebter.
Vielleicht bedeutet das, dass das irgendwann dann auch in diese Richtung driftet.
Ja, mal schauen.
Wer weiß.
Ja, Import Sys.
Import Sys ist dann auf Python, ja.
Ich glaube, das hatten wir letztes Jahr auch schon mal.
Ziemlich genau um diese Zeit.
Hatten wir das nicht in der ersten Folge schon mal am Schluss, glaube ich, ja.
Und aber kann man sich auf jeden Fall immer mal wieder angucken.
Ja, also den Interpreter öffnen, einfach Import Sys eingeben und abschicken und dann seht ihr das dann auf Python.
Also die Prinzipien, die man sich darauf geeinigt hat, hier in Python gelten sollen, wäre auch selber.
So ein bisschen Humor mit dabei und aber ja, ist auch was dran.
Ja, das ist direkt verknüpft zu PIP 8.
Ich glaube, das hatten wir dann auch schon mal kurz erwähnt, aber an der Stelle ist es vielleicht nochmal.
Sozusagen einfach nur die Art, wie man relativ minimalistischer Konsens darüber, wie man Python-Code formatieren sollte, vielleicht.
Und je, wer macht das nicht?
Dann kommt hier in die Python-Hölle.
Ja, aber auch innerhalb von Pype 8 gibt es halt so Dinge, die dann nicht geklärt sind dadurch.
Und Black hat halt zum Beispiel eben eine Meinung dazu, wie das sein soll.
Du kannst ja Dinge.
Das ist bei einigen Sachen total furchtbar, das sieht scheußig aus.
Okay, was denn?
Ja, wenn ich zum Beispiel Argumente in Funktionen packe oder längere Print-Statements schreibe, wie er die dann umbricht, dann macht er die Klammer auf in eine Zeile, dann nächste Zeile den String aus dem Print-Statement und dann darunter die Klammer wieder zu, wo ich dann sagen würde, hey, für die fünf Zeilen extra, wenn das Print-Statement eh länger als 89 Zeichen ist, hättest du das auch einfach in eine Zeilen schreiben können.
Oder halt, wenn Kommentare am Ende der Zeile sind, dann bricht er dann trotzdem die ganze Funktion auseinander, obwohl sie noch reinpassen würde.
Oder wenn Black sagt, ganz viele Argumente in einer Funktion, bricht das dann aber um, weil es nicht genug Argumente sind, um auf jeder Zeile ein Argument zu haben.
Das sieht auch ganz furchtbar aus.
Und dann ist dann der, klar zu mit dem Doppelpunkt dann am Anfang von einer Zeile irgendwie drei Zeilen Funktionsdefinition.
Das finde ich total furchtbar.
Ich bin eh nicht so ein Freund von diesem 89-Zeichen-Editor-Quatsch, weil ganz ehrlich, so Enzien, dass wir nur 89 Zeichen auf dem Bildschirm haben, ganz, ich entwickle.
Ja, 79, Entschuldigung, ich entwickle nicht die ganze Zeit mit meinem Telefon.
Nee, das ist für Konsolen eigentlich.
Die haben halt bloß 80 Zeilen, also 24 Zeilen, 80 Spalten.
Und es gibt natürlich, oder ich weiß nicht.
Ja, die alten, aber nur, also die neuen.
Weiß ich nicht, ob es dann.
Nee, nee, der Standard ist immer noch so.
Also wenn, äh, es ist auch so, wenn du, wenn du jetzt auf dem Linux oder so bist, dann hast du ja nicht unbedingt immer ein grafisches System und deine Konsole sieht halt so aus.
Da gibt es keinen.
Ja, aber auch bei VI hast du ja mehr.
Auf einer Konsole.
Ja, also ohne grafische Benutzeroberfläche, glaube ich, ist schwierig.
Aber auf der anderen Seite wahrscheinlich gibt es diesen Fall, dass jemand am Rechner ohne grafische Benutzeroberfläche sitzt, praktisch gar nicht mehr so.
Also, wenn ich mich auf meinen Server einlogge, habe ich da mehr als 80.
Ja, natürlich, aber du hast nur mal eine Shell.
Hast du dich mal an eine Konsole gestellt, an einem Rechenzentrum, an eine serielle Konsole?
Ich glaube, da hast du genau die 80 Spalten und 24.
Das ist ja uralt-DOS, also das ist jedes.
Ja, bei DOS war das auch so, genau.
Ja, ich weiß ja auch.
Also ich glaube auch nicht, das ist eigentlich nicht mehr relevant, aber da kommt das halt her.
Selbst wenn dann sieht man da halt, muss man kurz drauf aufpassen, dass es dann umgebrochene Zeilen gibt.
Die automatisch vielleicht eingeguckt werden oder so.
Ich weiß gar nicht, auf was ich es gestellt habe mit mir.
Das ist ja auch ein Ding, das man bei Black tatsächlich einstellen kann.
Also da, das muss man nicht so auf 79 Zeichen lassen.
Also 79 Zeichen, deswegen, weil man halt noch eins braucht für ein Zahlenummer.
Aber wenn, also ich weiß, ich glaube, ich habe es auch auf eine 10 stehen, aber ich weiß es nicht.
Aber jedenfalls, das kann man ja konfigurieren und dann ist es nicht mehr so schlimm.
Also ich finde auch ein bisschen mehr als 80 geht schon.
Ja.
Irgendwann ist es natürlich auch wieder doof, wenn das halt zu lang wird, lesen.
Also so, dass man es halt vernünftig auf einen normalen Arbeitsrechner irgendwie von sich anlesen kann, dass er nicht immer halb so groß ist, dass man viel zu viel Platz braucht.
Das wird ja völlig unabsichtlich und hässlich, einige Sachen.
Also ich finde, das Deck ist dann so ein bisschen inkonsistent, wenn es halt dann beispielsweise, was?
Drei Debug-Statements hintereinander, das eine ist vier Zeichen zu lang, dann bricht der es ganz komisch um irgendwie und die anderen darunter sehen nicht so aus.
Das ist irgendwie komisch.
Naja.
Also ich
finde, mein ästhetisches Empfinden wird er immer so ein bisschen angehen.
Naja, gut.
Wann ist man am Niesyndrom erkrankt?
Ah, not invented hier, ja.
Das hat sich auch nicht mehr so gut.
Wenn man alle offenbar macht,
sehr böse erwischt.
Ja, das ist halt das Problem.
Genau, das heißt einfach nur, dass man halt versucht, alles selber zu machen und wenn es halt nicht von hier kommt oder so, viele Firmen haben das auch, die alles doof finden, was sie nicht selber gemacht haben und dann halt viel zu viel selber machen.
Das ist natürlich ein Problem.
Genau.
Ist halt immer nett, da kann man immer was mit lernen.
Also dann die Grundlagen zu verstehen, ist gar nicht so schlicht.
Und hat man irgendwann nicht keinen mehr, der versteht, wie es irgendwann mal gebaut worden ist.
Sondern nur noch Leute, die dann irgendwie auf dem Sand und der Asche von alten versunkenen Städten versuchen, neue Gebäude zu errichten und auch immer so, oh, da war eine Grube.
Und dann stillst du ja Palast zusammen.
Das ist natürlich dann das, was man vielleicht verhindern will.
Und deswegen ist das vielleicht auch gar nicht immer so schlecht.
Aber natürlich kann man ja viel Zeit damit verschwinden, dass man einfach anfängt komplett das Rad nochmal neu zu erfinden, wo man eigentlich schon irgendwie fliegen könnte.
Ja, es ist immer schwierig.
Man muss da halt eine richtige Balance finden.
Es ist manchmal gut, Dinge, also ein Beispiel dafür wäre auch dieses Timestamp-Modell aus den Model-Utils.
Deswegen haben alle als Abhängigkeit Model-Utils drin.
Dabei, ja, wir haben es dann auch so, wie man über Django 3 kurz auch gesprochen und da hat er dann so, naja, das sind halt eigentlich zwei Zeilen, irgendwie in einem Modell, wenn man das selber macht.
Das ist, vielleicht wäre es besser gewesen, die beiden Zeilen dann selber hinzuschreiben und dann diese Abhängigkeit nicht zu haben, weil jetzt hat man halt das Problem, dass wenn man das ja auch wieder blöd, wenn man nichts selber macht.
Ganz schlimm im MPM hat das ja auch so bei JavaScript-Geschichten, dann hast du halt, musst du dich halt viel mit dieser Maintenance von diesem Kram beschäftigen, was ja auch blöd ist.
Also eine Queversionierung muss immer stimmen und genau dem Stuchstand bleiben und wenn du dann irgendwelche Bugs hast, musst du dann irgendwas updaten, weil irgendwas kritisch war.
Und das hat dann andere Abhängigkeiten und dann fliegt ja irgendwas auseinander, weil das inkompatibel ist mit irgendeiner neuen Implementierung von irgendeiner.
Also es ist halt auch, man kann nicht sagen, das eine ist super schlecht, das andere ist, sondern es ist halt, man muss halt irgendwie da einen irgendwie einen Weg finden, der für einen für den Anwendungsfall, den man hat, den besten Trade-Off bietet.
Ja.
Aber tatsächlich ist es so, dass die meisten Leute eher zu viel Richtung notinented hier gehen.
Ja, manchmal ist das praktisch.
Ich glaube, manchmal ist es auch gar nicht so schlecht, wenn man einfach coole Sachen, die cool funktionieren, einfach benutzen kann und die dann cool weiter funktionieren und dann auch einem schnell irgendwas ermöglichen zu entwickeln.
Ich glaube, gerade für Anfänger ist das gar nicht so schlecht, wenn man halt nicht von ganz immer anwenden kann, obwohl es natürlich auch nett ist, wenn man vielleicht erstmal Assembler lernt und dann C und dann irgendwie guckt, wie es alles so funktioniert, aber es ist auch vielleicht ein bisschen aufwendig.
Man kann vielleicht auch ab und zu mal eine High-Level-Bibliothek einfach benutzen, um zu gucken, wie man Dinge damit anstellt, ohne direkt alles zu verstehen oder selber zu implementieren.
Ja.
Über die Zeit ist es natürlich so, dass auch der Level an Abstraktion, auf dem man arbeitet, ist halt immer höher eigentlich, weil halt immer mehr wird Commodity.
Also die Sachen, die früher der interessante Bereich war, in dem man irgendwas gemacht hat, die werden halt zunehmend Community und wandern halt sozusagen aus dem interessanten Feld raus.
Und das, wo man die interessanten Sachen machen kann, das geht über die Zeit immer in abstraktere Geschichten.
Das ist halt auch die Frage, inwiefern das nicht unter Umständen, also auf der einen Seite kann man sagen, man kann halt schon mit viel mehr viel weniger Zeilen-Code irgendwie viel kompliziertere Dinge und tollere Sachen bauen.
Auf der anderen Seite ist es halt, wenn man sich das manchmal genauer anguckt, ist halt einen, steht das alles so ein bisschen auf Tönernden Füßen.
Das ist halt so Kartenhaus über Kartenhausgeschichtet.
Und irgendwie auf den unteren Ebenen sind stimmen schon viele Sachen nicht mehr so richtig, aber dann baut man halt so lange Abstraktionen drüber, bis es wieder, also ja, aber in Wirklichkeit hat man diese Probleme nie wirklich gelöst.
Wenn man halt das Gebäude den Palast aus der Sandgrube baut, man kann tatsächlich ein paar Stahlträger einziehen, dass man so tut, dann könnte der Palast halten.
Das ist halt dann, ja, und ja.
Ja.
Ja, aber jetzt gehen wir, glaube ich, jetzt haben wir so ein bisschen generell darüber gesprochen, was so, ne, Python generell, was hast du ausmacht.
Jetzt gehen wir also ein bisschen tiefer in die Probleme der, oder was heißt die Probleme, die Ideen, die Konzepte der eigentlichen Sprache, was man da vielleicht achten muss.
Also falls ihr noch Fragen habt, die ihr nicht beantwortet hattet, ne, schreibt uns wieder, wie immer.
Hallo.python Podcast.de.
Wofür ist die InitPy?
Hm, das ist eine gute Frage.
Ja, man braucht das irgendwie, damit es ein Paket ist.
Ein Modul, wo ist der Unterschied zwischen Modul und Paket?
Oh mein Gott.
Ich glaube, das muss ich ja selber nochmal nachlesen.
Damit der Namespace irgendwie vernünftig zugegriffen werden kann.
Also alles, was man da irgendwie reinpackt, das sitzt dann im Namespace dieses Moduls, wenn man es importiert, direkt drin.
Irgendwie so und dann kann man da direkt aktiv drauf zugreifen.
Aber die Frage ist halt, warum man das dann nicht dann mit einem Submodulen macht?
Nee, du kannst das ja auch, du kannst es ja auch reinschreiben, was du exportieren willst, welche Symbole.
Interessante Frage ist, kann man da auch Sachen ausschließen?
Also dass ich zum Beispiel sage, ja, aus diesem Modul bitte nicht in den Namespace packen oder sowas.
Also es kommt noch eine andere Frage von einem Hörer von uns, der wissen wollte, wie das dann überhaupt so funktioniert, dass man Module selber bauen kann.
Ich glaube, das Einzige, was man machen muss, ist halt einen Folder importieren, also indem man halt relativ einen Zugriff drauf hat und dann einfach sagen, Import Foldername oder sowas.
Und wenn da eine Init-Py drin ist, dann kann man die Module, die da drin sind, einfach aufrufen.
Mit einem Import halt.
Und dann kann man from Modul Verzeichnisname Import Python-Datei oder from Modulname Punkt Python-Datei Import Funktionsname.
Und dann kann man die einsetzen auf dieser lokalen Ebene.
Und die Frage wäre halt jetzt, warum man diese InitPy an der Stelle braucht und was die halt vielleicht macht.
Und dass sie vielleicht halt dieses Namespacing, was in Python auch auch irgendwie so ein Ding ist, also das zum Beispiel zu sagen, welcher Name jetzt zu welcher Funktion, zu welcher Sublibrary gehört, dass das da ein bisschen definiert wird.
Ja, man kann auf jeden Fall an der Stelle kontrollieren, was halt eben, was mit welchem Namen exportiert werden soll, sozusagen.
Und dafür ist es ganz nötig.
Warum man sie unbedingt braucht, weiß ich nicht so genau.
Und das ist auch etwas, was mir schon öfter mal auf den Fuß gefallen ist und wahrscheinlich vielen Leuten, die jetzt, dass man halt kriegt manchmal so wenig hilfreiche Fehlermeldungen, wenn man die Init-PY vergisst, sozusagen.
Oder wenn die aus irgendwelchen Gründen abhanden gekommen ist, was ja auch manchmal vorkommen kann.
Und dann kriegt man Facebacks, die sehen irgendwie komisch aus.
Und man sieht denen nicht sofort an, dass seine Init-PY fehlt.
Irgendwann weiß man halt einfach so, ach, da sieht jetzt danach aus, okay, das könnte sein, dass er einfach die Init-PY fehlt, aber.
Ich habe zehn Minuten da vor meinem Bildschirm gestanden und überlegt, warum macht er jetzt nicht die Migrationen von meinem Dank-Modellen, die ich da geschrieben habe?
Verstehe ich nicht.
Und dann fehlt halt einfach die Initpile, Migrations-Holder und dann.
Also ach so, ja klar, kennt er ja nicht, kann er ja gar nicht sehen.
Aber da muss man auch drauf kommen tatsächlich sonst.
Ja, das ist so ein bisschen, genau.
Und eben, ja, also gute Idee mit, was sind eigentlich Paketemodule, wie funktioniert eigentlich Importsystem und so müssen wir uns auch nochmal beschäftigen, aber da müsste ich mich auch erstmal anlesen.
Das weiß ich jetzt alles gar nicht so genau.
Ja, dann
kriegen wir bestimmt noch jemand.
Aber wir haben ja die Minute schon wieder überschritten.
Ah ja, gut.
Aber Innepai ist halt, wenn man dann, also Doppel-Anderscore am Anfang und am Ende.
Also wofür brauchen wir überhaupt ein Underscore und wofür zwei?
Ja, also ich glaube, das ist.
Also die Konvention ist es.
Und ich glaube, früher war es mal nicht nur eine Konvention, aber mittlerweile ist es tatsächlich nur Konvention, dass man Sachen, die halt innerhalb einer Klasse oder innerhalb, also Dinge, die halt sozusagen private API sind oder privat benutzt werden, aber nicht nach außen, eigentlich nicht von außen benutzt an, äh, also angefasst werden sollten, die werden halt mit Doppel unter Underscore halt irgendwie gepräfixt.
Und Sachen, die halt sozusagen, dann gibt es einfach einen Underscore, das ist halt so markiert für ja, also kann man nicht, sollte man nicht, es ist auch eher so interner Gebrauch, ja, aber es ist jetzt nicht so total privat.
Ja, also ist es eine Konvention.
Im Grunde braucht man das auch, also außer jetzt manchmal bei Doppel Underscore eigentlich auch nicht wirklich.
Also ich habe zum Beispiel diese internen Variablen, habe ich noch nicht verstanden, wofür das gut ist.
Ich habe es auch noch nie benutzt, außer jetzt im Magic-Method-Kontext von Klassen, wo man halt dann irgendwelche magischen Methoden, die es im Internet überschreiben will, um andere Effekte zu erzeugen.
Ja, es ist halt so ein Hinweis darauf, dass man da nicht wirklich mit interagieren sollte, sozusagen raus.
Fast meine Klassen nicht.
Bitte nicht daran vor, also
alles, was man selber schreibt, macht man anderskopf vor, damit nicht anderes anfasst.
Nee, nee, ich versuche mal ein Beispiel zu geben.
Also wenn du eine Klasse hast, die irgendwas cached, dann packst du halt, wenn, also du rechnest es halt aus, du überprüfst in einer Methode, ja, also sozusagen ein bestimmtes Attribut ist eine Property von dieser Klasse, also hat einen Property-Dekorator drüber, irgendwas wird ausgerechnet.
Und du schreibst das Ergebnis dieser Berechnung, also prüfst, wenn du die Motor aufrufst, zuerst habe ich das schon ausgerechnet.
Wenn ja, gibst du einfach den gecachten Wert zurück und ansonsten rechnest du es halt neu aus unter bestimmten Bedingungen.
Und den Cache selber, den legt man oft dann in so einem Underscore irgendwie Attribut ab.
Anderscore Cache.
Ja, oder Anderscore dieses, äh, dieser, dieser Name dieses Attributes oder so.
Weil, äh, und das heißt halt ja bitte nicht anfassen, weil das Problem ist jetzt, wenn ich von außen da rangehe, dann kriege ich vielleicht den gecachten Wert.
Aber ich kenne ja jetzt gar nicht die Bedingungen, unter denen das vielleicht den Cache invalidieren müsste oder so.
Und wenn ich da jetzt einfach so drauf zugreife, dann kann es sein, dass Ding schief gehen.
Und das heißt, ja, das ist halt so eine Markierung für das Ding hier bitte nicht direkt verwenden, sondern dann gibt es ja meistens ein öffentliches Attribut, was man benutzen kann und dann kann die Klasse das intern handeln.
Was hat das denn überhaupt eine API?
Ja, im Grunde eine Schnittstellen, die Schnittstelle zu irgendwas.
Das gibt es jetzt auch in unterschiedlichen Kontexten kann man das verwenden, aber ich würde jetzt mal sagen, also üblicherweise, wenn man jetzt irgendein Paket verwendet, weiß ich nicht, es halt Party-Django-Paket oder irgendeine Python-Bibliothek oder so, dann ist die API das, was man sozusagen von außen benutzt.
Die besteht ja aus ganz vielen Funktionen, vielleicht.
Die Kliesen, die man für seine Bibliothek benutzen kann, um die
anderen damit
irgendwas zu machen.
Also wenn ich jetzt zum Beispiel jetzt Requests nehme oder so, dann macht Requests.get macht halt einen Get-Request.
Das ist halt der öffentliche.
Intern macht das dann unter Umständen noch eine ganze Menge andere Funktionsaufrufe und Dinge und weißer Teufel.
Und die
sind aber intern gar nicht alle mit einem Underscore.
Nö, also manche von denen kann ich auch einfach so verwenden, das ist ja auch gar kein Problem, aber andere wahrscheinlich auch eher nicht.
Und die, die ich nicht unbedingt verwenden sollte von außen, die sind halt dann so markiert als für intern gebraucht.
Ja.
Was ist eine Privat und eine globale Variable und was ist der Unterschied und wofür braucht man das?
Global, privat, also privat, öffentlich, das ist halt so ein bisschen, aber das hat man in Python eigentlich auch gar nicht so wahnsinnig viel.
Also es gibt in anderen Programmiersprachen gibt es da eine stärkere Unterscheidung, aber also im Grunde ist es einfach.
Also ich hatte es gerade so in den ganz Anfängertagen ganz oft so, dass ich irgendwie mir dachte, so ja, private Variablen, das ist alles irgendwie ein bisschen blöd, ich muss ja irgendwer von einer Funktion immer irgendwie so einen Wert return und damit das dann, also ich glaube im Kontext einer Funktion sind ja die eigentlich die Variablen immer privat.
Nein, nein, nein, nein, das ist eine Verwechslung.
Also du meinst lokal, lokal und global.
Privat und öffentlich, das ist halt genau diese Geschichte mit dem Double Andersquader.
Ja, okay.
Dann meinte ich lokal und
global, ja.
Also lokal heißt, Variablen sind halt quasi in dem Block gestellt.
Gültig, in dem global.
Und ich habe mir gehört, man braucht keine globale, man darf die nicht nehmen und das ist total nicht so Backquest.
Kann man schon.
Also gerade ich habe manchmal so Spielereien gemacht, Spiele gebaut oder sowas.
Da haben das hat das immer total super geholfen, weiß ich nicht, die Lebensenergie des kleinen Männchens global zu definieren, anstatt in einer Funktion oder so.
Ja, ja, nee, kann man durchaus machen.
Es gibt auch Fälle, wo man das, wo das durchaus praktische Anwendungsfälle hat.
Ist jetzt nicht unbedingt immer so guter.
Also es kommt halt darauf an, was man damit machen möchte.
Also man muss das halt explizit halt dann als global markieren, wenn man das tun möchte.
Und dann gibt es auch noch, glaube ich, nochmal einen Unterschied zwischen nur global oder global für ein Modul oder aber ja, also für manche Sachen ist das durchaus, also gerade irgendwelche Konstanten oder so, die definiert werden, die sind oft global.
Also wenn man das nicht ändert, ist das ja auch nicht schlimm.
Wenn man jetzt globale Variablen hat, die man ändert, dann ist so ein bisschen, das riecht dann schon so ein bisschen danach, als ob da irgendwas nicht so richtig ordentlich funktioniert, weil was möchte man damit eigentlich machen?
Also man hat da irgendwie State, auf dem man zugreift von unterschiedlichen Stellen.
Also es wird dann halt sehr schwer zu debuggen und sehr schwer vorauszusagen, was da eigentlich passiert, wenn man das einfach so verwendet und an unterschiedlichen Stellen des Codes das dann ändert einfach so.
Da muss man sich halt sehr, sehr genau überlegen oder man muss halt, also vielleicht fange ich so rum an.
Das Problem beim Programmieren ist dann halt irgendwie, dass ich an der Stelle, wo ich das ändere, muss mir ja immer klar sein, was an allen anderen Stellen im Code, an denen an diesem Ding irgendwie rumgeschraubt wird, auch passiert.
Was?
Also ich nehme jetzt mal so ein Beispiel, wo ich jetzt intuitiv sagen würde, das wäre jetzt für mich das, was ich jetzt als globale Variable lernen würde.
Ich habe jetzt ein Spiel, mein Baba hat Lebensenergie vor 100.
Und es gibt bestimmte Funktionen, die aufgerufen werden.
Wenn der Babar irgendwas macht, falsch macht, richtig macht, runterfällt, gegen einen anderen, gegen Monster kämpft, dann würde ich von dieser globalen Lebensenergie irgendwas abziehen.
Wofür muss ich denn dann an der einen Stelle, wenn er jetzt, weiß ich nicht, auf ein Skelett trifft, dem 10 Lebensenergie abzieht, wissen, was an der anderen Stelle die Falle mit ihm gemacht hat?
Naja, also weil du, weil, weil der, naja, lass mal überlegen, kann ich irgendwas konstruieren, was dann problematisch wird?
Ich meine, es kann ja auch Dinge geben, die die Lebensenergie wieder erhöhen.
Ein Trank.
Ja, und du musst halt zum Beispiel, du musst halt wissen, dass das jetzt schon nicht unter Null gefallen ist, wenn du dir jetzt, äh, sonst könntest du dich ja auch wieder lebendig machen.
Sozusagen, wenn du tot bist, eigentlich.
Ein Lifehack, ja.
Du musst irgendwie den, den, ja, irgendwas muss diesen State verwalten.
Irgendwas muss halt sagen, okay, jetzt bist du aber tot.
So.
Und dann darfst du nicht durch, darf nicht irgendein anderer Teil des Codes, der jetzt nicht weiß, ob du tot bist oder nicht, einfach deine Lebensenergie oder deine Lebenspunkte erhöhen, weil das macht dich ja eventuell wieder lebendig in einer Situation, wo das gar nicht gehen darf.
Also sozusagen ist es.
Also das würde nicht so gut funktionieren.
Das heißt, da würde man auch klassenbasierten Ansatz nehmen, wo man irgendwie sowas machen wie Erhöhe Lebenspunkte und reduziere Lebenspunkte und der macht das halt dann nur dann, wenn man dann nicht tot
ist oder so.
Genau, und das Erhöhe Lebenspunkte geht halt nur, solange man nicht tot ist, zum Beispiel und so.
Aber diese Logik, wie das funktioniert, wäre dann halt an einem Ort gebündelt.
Das ist ja so ein bisschen die Idee auch hinter Klassen, überhaupt hinter Objekt oder Chatter-Programmierung, dass du halt die ganze Komplexität irgendwie verbirgst hinter dieser Objekt, hinter einer AP, genau, und dann das halt alles nicht mehr wissen muss.
Während wenn du jetzt einfach nur eine Variable hast, die da irgendwie verändern kann, dann ist die Komplexität verteilt über den gesamten Code irgendwie, der mit dieser Variable interagiert.
Was wäre
denn jetzt aber ein cleveres Beispiel für eine globale Variable, wo man sagen würde, hey, da macht das irgendwie jetzt dann doch Sinn?
Ich würde ich, nee, mir fällt da fast keins ein, wo das irgendwie sinnvoll ist.
Also was man manchmal hat, ist, dass man sicher sein möchte, dass man etwas nur einmal hat oder so.
Aber da würde man auch eher einen Singleton nehmen, beziehungsweise in Python eher Borg Pattern.
Oh, Singleton, das steht hier ein bisschen weiter unten, ein Singleton.
Borg-Pattern, hast du gerade gesagt.
Ja, okay.
Was ist ein Singleton, was ist ein Borg-Pattern?
Ich wollte wieder anfangen.
Also sozusagen Singleton ist, wenn garantiert sein soll, dass es von einer bestimmten Geschichte nur eine Instanz gibt.
Also wenn ich zum Beispiel eben in einem Spiel der, weiß ich nicht, die Spielfigur oder so, die eine bestimmte Eigenschaften hat, wie eben sowas wie Lebensenergie oder so, wenn ich garantieren möchte, dass alle, die damit interagieren, immer die gleiche Instanz sehen.
Dass ich halt den nicht, weil es gibt nur einen, es wäre jetzt blöd, wenn ich zwei davon erzeuge und dann in dem einen Objekt verringere ich die Lebensenergie und im anderen nicht oder so.
Wie macht man das denn?
Überschreibt man dann die New Methode und sagt dann so, nee, wenn es schon eins gibt, dann mach keinen neuen?
Ja, das ist, äh, nee, eigentlich, also so weiter, also dann kommen wir zum Borg Python, so wird das üblicherweise dann in Python implementiert, ist, man macht es einfach so, dass.
Wie ging das doch?
Also ich glaube, der Trick ist, aber das muss man mal nachgucken, also mit Vorsicht genießen, ist, dass sozusagen den State innerhalb eines Objekts sozusagen in einer Klassenvariable zu halten, die halt bei allen Instanzen gleich ist.
Und das können die Instanzen zwar unterschiedlich sein, aber der State ist immer gleich.
Und dann ist es zwar kein Singleton in dem Sinne, wie man das vielleicht ursprünglich mal so definiert hat.
In Gängervorbuch gibt es halt das Pattern Singleton, weil man eben nicht immer tatsächlich, also ich glaube, die bei ursprünglichen Singleton-Beschreibungen ist es so, das wird einfach immer die gleiche Instanz returnt, wenn man halt die.
Also das hast du nie überschreiben.
Das würde halt bedeuten, wenn es schon ein anderes gibt, du returnst halt das, weil.
Returnst du das Alter halt, sowas kann man auch in Python machen, das wäre gar kein Problem, aber praktischer ist es halt, weil es einfach weniger Code und macht sozusagen, verhält sich ähnlich und hat noch ein paar andere nette Vorteile, dass du halt sozusagen sagst, der State ist über alle Instanzen verteilt, äh, über alle, über bleibt über alle Instanzen von diesem Objekt gleich.
Und ich muss da nicht kompliziert irgendwie dafür sorgen, dass ich immer die gleiche Instanz zurückgebe, weil wen interessiert es?
Ja.
Ja, aber genau, das sind alles, es geht immer so um State-Handling im Grunde.
Das ist immer so das, und wer manipuliert denen und wie kann man dafür sorgen, dass der, dass man den Code, der den State manipuliert, an einer Stelle behält und so und nicht, weil das sind immer so, das ist was, was halt man am Anfang, das ist ein bisschen unintuitiv, denkt man sich so, naja, das ist ja kein Problem, State kann irgendwo sein, egal, ist in einer Variable, einer globalen Variable oder so oder halt auch oft verteilt oder man hat die Klassen sich mal irgendwie überlegt, wie so eine Klassenhierarchie aussehen soll oder
so, aber und zieht das dann durch, unabhängig davon, wie das Problem eigentlich ist.
Und das fiese, was manchmal dann oder was immer passiert irgendwie, ist, dass man dann halt den State verteilt über viel Code und dass man
dann halt.
Das, was sich, das, was du speichern musst, was sich irgendwie ändert.
Also der Status.
Also sagen wir mal so, bei einer Web-Applikation würde man sagen, das ist der State einer Web-Applikation, liegt üblicherweise dann eben in der Datenbank.
Also das ist so einer klassischen Basis-Konferenz.
Ja, die Fall jetzt auch da war.
Also was bedeutet das?
Also was ist denn überhaupt dann der State?
Sagt der, wie der Nutzer gerade aussehen soll, wie der heißt und was er für Daten gespeichert hat für sein Profil, was er sehen soll.
Und dass es halt nicht dynamisch generiert, sondern liegt dann irgendwo rum.
Das heißt, wenn man das ändern möchte, dann muss man erst die Datenbank fragen oder sowas, das macht man ja gar nicht woanders.
Ja, genau, genau.
Also du ja, also das, was halt sozusagen beschreibt, in welchem Zustand deine Applikation ist, sozusagen.
Gehen wir jetzt nochmal aufs Spiel kurz.
Also was du denn Figur ist.
Was hat die gerade für eine Waffe in der Hand?
Was für den Telegie hat die, wie viel Rüstung hat die noch an?
Was das wäre der State?
Genau, wenn
du jetzt irgendwo in einen virtuellen Laden und kaufst dir irgendwie das magische Sonst was Schwert, Feuerschwert, mit dem du irgendwie alle platt machen kannst, dann muss ja irgendwo gespeichert werden, dass du das jetzt hast, dass das dein Adventure ist.
Und es darf aber auch keine zwei gleichzeitigen Sachen dann irgendwie haben.
Dass es sich jetzt nicht widerspricht, darf es immer nur ein State geben.
Das so das, was dahinter steckt.
Nee, die interessante Frage ist, wie verwaltet man diesen State sozusagen?
Und naiv wäre halt, man hat halt zum Beispiel hält das halt in irgendwelchen globalen Variablen.
Man hat halt eine Liste.
Linker Hand, die ist halt global und dann genau, da steht halt drin, ja, hier ist ja halt das Flammenschwert und das ist da jetzt in dieser Liste der Items drin.
Und alle manipulieren diese Liste von Items irgendwie, aber das macht dann halt Probleme, weil dann muss, dann ist Logik, die jetzt irgendwie solche Sachen abbildet wie das Flammenschmert macht jetzt plus 10 Angriff, aber auf der anderen Seite wird dir heiß, das heißt, äh, wird die Hand heiß und du verlierst irgendwie alle halbe Stunde ein paar Lebenspunkte oder sowas, keine Ahnung.
Das ist der Code, der irgendwie diese Business-Logik, wenn man das so sagen kann in dem Spiel, halt implementiert.
Und das kann ja sein, dass da unterschiedlicher Code an unterschiedlichen Stellen steht.
Und wenn du jetzt überall das gleiche globale, die gleiche globale Variable hast, auf die du zugreifst, dann musst du dafür sorgen, dass dieser gesamte Code, der halt über dein Projekt verteilt sein kann, dass der immer weiß, was alle anderen Sachen machen.
Und das geht irgend auf einer gewissen Größe nicht mehr.
Am Anfang geht das, sobald es alles sehr klein ist, kriegt man das auch noch hin, dass man das alles im Kopf behält.
Ja, also du musst halt jedes Mal zumindest diese Überprüfung machen.
Du musst halt jedes Mal gucken, hat denn jemand irgendwas geändert an der Stelle, das nicht sein darf.
Das heißt, jede dieser Logiken müsstest du bei jeder Stelle, wo diese globale Variable geändert wird, erneut machen, was halt dem Don't repeat yourself widerspricht und so.
Das kann schon durchaus so sein, dass man sich da nicht wiederholt, aber du kannst halt Änderungen machen, die dann nicht lokale Auswirkungen haben.
Also nehme mal an, du weißt das halt alles nicht.
Du weißt halt, du machst jetzt halt ein neues Item, sozusagen, das irgendwelche Spezialgeschichten hat, schreibst da Code für, dass das halt irgendwie tut.
Und dabei bedenkst du aber nicht, dass unter bestimmten Umständen irgendwelche anderen Code irgendwas anderes tut.
Und dann passieren halt Fehler und seltsame Effekte.
Und solange man halt von dem ganzen anderen Code, der irgendwie daran rummanipuliert, irgendwie weiß, ist das ja okay.
Aber sobald das Projekt irgendwie größer wird, geht das irgendwann nicht mehr.
Und dann kann man überhaupt nicht vorhersagen, was passieren wird, wenn man jetzt irgendwie Dinge ändert, wie man manipuliert irgendwas an den Lebenspunkten oder so und dann gibt es irgendwas anderes, was wiederum nochmal was anderes macht.
Ich bin der Invincible Geist, der, ja.
Ja, und dann, also das Mittel dagegen ist halt, dass du eben nicht direkt die Daten hoch anfasst, sondern dass du sagst, okay, wir haben hier eine Klasse oder so und der ist, bündeln wir den State, also die Daten und die Logik, die jetzt irgendwas damit macht.
Und haben da eine API nach außen, die öffentlich ist und können sozusagen immer überprüfen, dass alles ordentlich ist an einer Stelle.
Und dann, ja.
Ja, die Frage war, was ist ein Objekt in Python?
Was ist ein Objekt in Python, ja.
Ich würde es jetzt mal sagen, so erklärt aber nicht viel, ist halt die Instanz, konkretisierte Instanz von irgendwie einer Klasse.
Alles Objekt in der Klasse.
Mit einer Klasse definiert man sozusagen irgendwie, ja, eben eine Zusammenfassung von irgendwie Code, der was tut und irgendwie Daten, die man irgendwie halten will.
Und wenn man das jetzt, das ist halt sozusagen die Beschreibung und wenn man da jetzt.
Ich denke, ich habe gesagt nicht so besonders an von dem Code, der irgendwie Beschreibung von irgendwelchen Sachen.
Ja, also man könnte das vielleicht, also
ein Objekt ist ein Ding.
Also ich glaube in Python ist alles ein Ding oder ein Objekt, oder?
Alles ist ein Objekt, ja.
Also alles, was es in Python gibt, kann sich als Objekt darstellen.
Ein Objekt ist immer eine Instanz einer Klasse, kann man das so sagen.
Ja.
Das heißt, alles, was ihr habt in Python, sind tatsächlich Instanzen von irgendwelchen Klassen, von irgendwelchen Dingen.
Die nächste Frage war, was ist Self?
Self ist immer das Objekt selbst, also wenn man in einem.
Es ist auch eine Konvention, sozusagen, dass man das so nennt, aber sehr sinnvoll, das so zu machen.
Außer es gibt wiederum Spezialfälle, bei denen man das ein bisschen anders macht.
Also wenn man eine Methode hat, also Methode ist nichts weiter als eine Funktion, die sozusagen an so eine Instanz an so ein Objekt gebunden ist.
Und jetzt möchte man halt, um zum Beispiel auf die Daten, die man halten möchte, in so einem Objekt, um darauf zuzugreifen, muss man ja irgendwie sich selbst referenzieren können.
Deswegen wird immer als erstes Argument in Methoden, das ist halt auch das, was dann Methoden von Funktionen unterscheidet, immer eine Referenz auf das, auf sich selbst sozusagen mit übergeben.
Man könnte das auch anders nennen.
Man kann auch sagen, A statt Self, dann ist es A, aber es ist schon sinnvoll, das Self zu nennen, damit man weiß, dass es halt eine Referenz auf sich selbst ist, sozusagen, auf das Objekt, was man gerade ist.
Und dann kann man halt auf Self.irgendwelche Daten zugreifen.
Okay.
Da fangen wir jetzt direkt ein paar andere Sachen ein, weil wir jetzt das gerade erst so hatten mit Objekt, ne?
Was ist denn ein Objekt?
Ist das in einer Klasse?
Und jetzt gibt es irgendwie drei Dekoratoren, also wir müssen doch gleich darüber sprechen, was der ein Dekorator ist.
Aber es gibt drei Dekoratoren, die Python verwendet, die da immer so drüber stehen.
Static Method, Class Method und Property.
Über Property hast du eben auch schon.
Was ist denn jetzt da irgendwie so der kleine Hagen?
Also wann dacht man jetzt zum Beispiel, das ist eine statische Methode und wann sagt man das eine Klassenmethode?
Was heißt das denn in dem Kontext zu Self und Objekt und
Ja, also ich würde eigentlich am liebsten mit der Klassenmethode anfangen.
Also Class Method.
Class Method ist halt eine Methode, die eben nicht eine konkrete Instanz.
Das heißt, da fehlt auch Self bei der
könnte man jetzt auch Self übergeben, also es wäre dann sehr verwirrend.
Was man da üblicherweise übergibt, ist man CLS oder so und bekommt man die Klasse übergeben.
Die Klasse ist auch wieder ein Objekt.
Das ist auch irgendwie, man kann das dann noch ein Stückchen weiter treiben, auch dann mit Meta-Klassen hat.
Das kleinste Objekt, also jede Klasse ist irgendwie ein Objekt und das Objekt, Objekt und Objekt selber ist ein Objekt vom Typ-Typ.
Ja, okay.
Ja, okay.
Ja, also jedenfalls, wenn in der Klassenmethode übergibt man halt CLS und nicht Self, weil man damit man halt weiß, dass man jetzt gerade die Klasse in der Hand hat und nicht eine Referenz auf die Instanz.
Und es gibt halt, das Verwendet man vor allen Dingen dafür, dass man, es gibt halt bestimmte Methoden, die brauchen eben nicht, die müssen nicht auf irgendwelche internen Daten oder zugreifen, weil die hat man ja nicht.
Sondern die machen halt, die gehören zwar vielleicht irgendwie in die Klasse rein, weil die Funktionalität, die sie bieten, halt sehr viel zu tun hat mit der Klasse.
Aber die verhalten sich in gewisser Weise natürlich dann so wie eine normale Funktion.
Und vielleicht können sie auch auf Daten, die halt für alle Instanzen dieser Klasse gleich sind, zugreifen, eben über die Klasse, aber die brauchen jetzt nicht irgendwie eine konkrete Instanz, auf der sie irgendwas machen.
Also Beispiel für sowas sind, was wäre denn ein gutes Beispiel für
dem Spiel, also zwei Beispiele, die ich ganz gut visualisieren finde.
Entweder hat man so ein Spiel mit so Charakteren, oder man hat so ein Universum mit Planeten und Dingen, die umeinander kreisen oder sowas.
Zwei verschiedene Sonnensysteme als zwei Klassen.
Aber okay, lassen wir das.
Ich weiß nicht so genau, ob ich das da irgendwie, also mir fällt da jetzt gar nichts.
Also ich, man haut, also es sind oft irgendwelche Hilfsfunktionen oder so, die was machen, was logisch dann in eine Klasse gehört, aber wo man nicht mit einer konkreten Instanz irgendwas zu tun hat.
Mir fällt jetzt tatsächlich kein super tolles Beispiel.
Was ist denn der beste Unterschied zu der Static Method?
Was wäre das denn jetzt so als.
Ja, Static Method.
Aha die bekommt halt einfach tatsächlich überhaupt nicht mal die Klasse, ja.
Aber in Pressiv ist das nichts anderes, außer dass sie nicht mal die Klasse bekommt.
Das heißt, sie könnte man auch draußen hinschreiben.
Genau.
Das einzige Unterschied bei der Static Method ist halt, dass sie dann im Namespace der Klasse oder des Objektes aufrufbar ist oder so.
Ja, was ist jetzt in dem Vergleich eine Static Method?
Okay.
Ja, also Static Method bekommt gar kein automatisches Argument mit.
Also das wäre dann die reine, wäre quasi wie eine Funktion, ja, also es ist egal, ob man jetzt Static Method aufruft oder halt eine Funktion von draußen.
Funktion von draußen, genau, genau.
Ah, richtig, jetzt fällt mir doch wieder ein Beispiel ein zu Class Method, wo das wenn man jetzt in Django zum Beispiel Modelle hat, dann sind halt viele Geschichten, die jetzt ein Modell betreffen, die man von außen aufrufen kann, ruft man halt auf der Klasse auf und nicht auf der auf einer Instanz, weil eine konkrete Instanz ist ja zum Beispiel, man hat ja die Daten für die Geschichten stehen halt in der Datenbank und jetzt eine konkrete Instanz eines
, also Django-Modelle sind Klassen und sie modellieren sozusagen den Zustand, der irgendwie in der Datenbank steht.
Und eine Instanz üblicherweise ist halt eine Zeile.
Also wenn ich jetzt zum Beispiel Beispiel User nehme, ja, also ein User-Objekt in Django ist halt eine Zeile aus der Tabelle Users irgendwie und hat halt all die Attribute, die jetzt irgendwie die Zeile hat, als Spalten hat, sozusagen an dieser Tabelle.
Name, große.
Aber ich möchte jetzt möglicherweise Dinge machen auf der kompletten Tabelle.
Also auf allen Nutzern.
Ja, genau, auf allen Nutzern oder ich möchte einen neuen Nutzer erzeugen.
Ja, das kann ich ja jetzt nicht innerhalb von einem Nutzer machen, sondern das ist halt irgendwie, ja, und dafür sage ich dann irgendwas Users.Objects Create Create und das ist dann halt eine Class Method, die zwar sozusagen ja Informationen über die Klasse braucht und wissen muss, was man dann so tut.
Aber Users.create.
Streng genommen ist es ObjectsCreate, es ist halt der Model Manager, auf den man das aufruft, aber das ist halt dann ein Ding, aber dieses Objects ist halt
der Manager lassen wir jetzt mal kurz kurz weg, da muss man schon ein bisschen
Dango kennt.
Es ist nochmal komplizierter, aber dieses Objects ist auf jeden Fall ein Ding, was an der Klasse hängt von der und ja, was halt sozusagen, also man kann sich das so vorstellen, es betrifft halt die gesamte Tabelle.
Man erzeugt jetzt auf dieser Tabelle eine neue Zeile und das kann nicht eine Methode sein, die man auf einer Instanz aufruft, sondern
die halt Instanzen und die eine Zeile repräsentiert, weil innerhalb von der einen Zeile sich selber irgendwie ranzeigen würde, gar nicht so
richtig funktionieren.
Ja, könnte man auch machen, wäre irgendwie komisch.
Und warum nimmt man jetzt aber dafür jetzt nicht einfach eine Static Method?
Ja, könnte man auch, aber nee, kann man nicht, weil dann würde man halt zum Beispiel nicht mehr wissen, was sind denn jetzt die ganzen Stadt.
Und von der Tabelle wahrscheinlich.
Genau, man möchte ja auch wissen, welche Attribute gibt es, was muss ich eigentlich da und so, das, ja, das muss man ja auch, welche Tabelle ist denn das überhaupt, wo steht in der Datenbank?
Und das hängt halt an der, das sind Informationen, die an der Klasse dranhängen.
Und ja.
Das heißt, der Static Method würde mir sowas sagen wie, ist da draußen denn was anderes noch verfügbar?
Das könnte ich dann vielleicht gucken.
Static Method könnte sowas sein wie Hash mir mal das Passwort.
Also hier hast du einen String, mach mir mal einen Hash davon, den ich dann irgendwie in die Datenbank schreibe.
Das braucht gar keinen Kontext.
Das nimmt irgendwie einen String und gibt einen anderen String raus, das braucht aber sonst überhaupt nichts zu wissen.
Und das könnte dann eine Static Method sein zum Beispiel.
Aber es gehört halt logisch vielleicht schon in die User-Klasse, weil es halt irgendwie um Passwörter geht, die einen User eingibt und die dann halt irgendwie gehasht werden sollen.
Also das so hat man.
Property-Dekorator, ja, der ist, da geht es eigentlich nur darum, dass man ja so ein bisschen Convenience, dass man dann nicht eine Methode aufruft, sondern also man schreibt halt, also der häufigste Fall ist, man hat eine Methode, die nennt man so wie ein Attribut und schreibt dann AddProperty drüber.
Und dann wird halt diese Methode aufgerufen, wenn man irgendwo sagt, Instanz.
Also braucht man eigentlich nicht, man könnte auch eine Methode schreiben.
Ja, aber dann müsste man halt dann an der Stelle, wo man es verwenden will, Klammer auf Klammer zusagen, was halt so ein bisschen sinnlos ist, wenn man zum Beispiel gar nichts übergeben möchte an Argumenten und vielleicht auch etwas ist, was halt so aussehen soll, als wäre es ein Attribut, aber wo man Sachen noch ausrechnen will und dann kann man halt den Property Dekorator benutzen, um halt zu
quasi ein getarntes Methodending.
Ja, ist so manchmal ein bisschen, also das ist auch so, so diese Dekoratorgeschichte ist so manchmal ein bisschen, also ist dann auf Balten steht da sowas, explizit ist besser als implizit, ne?
Und das ist halt schon ganz schön implizit, dass wenn man jetzt irgendwo eben Instanz X.huber sagt, halt dann irgendwie Code ausgeführt wird, der irgendwas ausrechnet und dann unter Umständen auch sehr langsam sein kann, oder was auch immer, das halt nämlich unbedingt, also in dem Moment, wo man das halt lokal liest, weiß man nicht, was passiert, was immer so ein bisschen schlecht ist, ne?
Aber ja, es ist eigentlich normalerweise, wenn man dann komplizierte Sachen macht, dann sollte man das vielleicht dann auch eher als Methode hinschreiben und dann wird das dann vielleicht klarer.
Aber wenn man kurz vielleicht zwei Attribute hat, wie das eine ist Kosten, das andere ist Umsatz und dann will man den Gewinn ausrechnen, dann kann man vielleicht schon eine andere Funktion machen, die dann eigentlich kurz als Property sagt hier Umsatz gewinnen und dann
der ist einfach schnell aus.
Und ja, also man, und das, also das Get zu implementieren ist ja sehr leicht, und man schreibt irgendwie der Property drüber, dann war es das.
Das Set geht auch, also man kann es auch so machen, dass dann halt ein Setter aufgerufen wird, wenn man sagt, irgendwas, Instance X.fuber gleich irgendwie.
Das ist ein bisschen komplizierter, aber ja, geht auch so ähnlich.
Ja, also man kann, ich weiß nicht genau, man kann den Property Dekorator kann man glaube ich irgendwie sagen, so das ist hier der Getter, das ist ja der Setter oder was, ich weiß nicht genau.
Kann man dann nachgucken, wenn man es braucht, braucht man selten.
Also ich habe es ein paar Mal benutzt, aber nicht oft.
Aber überhaupt das Konzept von Dekorator.
Also das ist mal ganz gut, Getter Setter bedeutet halt, dass man die Attribute irgendwie von außen dann beeinflussen setzen.
Von der Instanz setzt bekommt oder setzt, genau, und zwar nicht direkt manipuliert, sondern halt Methoden dafür aufruft, die dann noch irgendwas vorher und hinterher tun.
Jetzt haben wir schon ungefähr 50 Mal Dekorator gesagt und du hast dann auch noch irgendwas anderes vorher.
Da muss man vielleicht nochmal erklären, was ein Dekorator eigentlich ist.
Eigentlich ist es eine sehr nicht so echt kompliziert werden.
Ja, es ist auf der einen Seite ein bisschen Spezialsyntax, diese Geschichte mit dem Ad-Symbol, dass man halt über Klassen und über Methoden, Funktionen schreiben kann.
Auf der anderen Seite ist es, man könnte es auch anders hinschreiben und da bräuchte man diese Spezialsyntax nicht, also die einem das so ein bisschen vereinfacht.
Man könnte halt auch hinschreiben, irgendwie x gleich Wrap mir mal eine andere Funktion, Wrap-Klammer auf, irgendwie eine andere Funktion, Klammer zu.
Und dann wäre das die dekorierte X die dekorierte Funktion.
Und man macht sich eine Tapete auf die Wand und unter der sieht man dann halt die Sachen anders.
Ah, die Form bleibt erhalten, aber die ist dann vielleicht rot oder blau.
Ja, also die Idee ist sozusagen, dass man etwas macht, also dass man halt Code hat, der ja man packt, deswegen ist Dekorator eigentlich auch ein, der zeichnet ziemlich genau, was es tut.
Input und Output, der rauskommt oder beziehungsweise reingeht, wird.
Wird nochmal, geht nochmal durch anderen Code durch und dann sozusagen, man kann halt, bevor irgendwas ist, bevor die Funktion aufgerufen wird, irgendwie Dinge damit tun und hinterher Dinge mit dem.
Das wird aber ganz vernünftig sein, wenn das durch einen Dekorator hat, der einen Dekorator hat, der einen Dekorator hat, dann.
Ja, aber normale Funktionsaufrufe macht man ja auch, ist auch okay.
Also das ist ja auch nichts anderes im Grunde.
Das heißt, wenn man einen Dekorator selber schreibt, dann baut man quasi einen eigenen Rapper und sagt halt, was passiert, bevor der da reingeht und wann der wieder rauskommt.
Ja, man sollte auch tatsächlich nicht wirklich, wenn man Dekoratoren schreibt, nicht das selber machen eigentlich, sondern man sollte für den Funktools Wraps oder so nehmen.
Und weil es gibt noch so ein paar Hackeligkeiten mit den Funktionsnamen zum Beispiel, die sonst verschwinden, wenn man, die sieht man in Tracebacks nicht mehr und da muss man so ein bisschen, und dann gibt es halt eben in den Funktools gibt es da, glaube ich, irgendwie Funktionen, die, wenn man die benutzt, um den Rekordator zu bauen, dann kümmern die sich um diesen Kram, sodass halt dann man in Tracwacks weiterhin die Namen sieht und so.
Also es ist ein bisschen.
Was hat denn das jetzt mit so einem Kontext zu tun, Kontextmanager oder was?
Oh nee, das hat aber nichts zu tun, das ist eine andere Geschichte.
Das hört er sich so ein bisschen so an, als macht man irgendwie so einen Kontext auf und rappt irgendwas und gibt das dann wieder, baut das dann am Ende wieder auseinander.
Hm, also, ja, also was eventuell irgendwie eine Gemeinsamkeit ist, dass beides irgendwie unten drunter vielleicht Closures verwendet, als wie das umgesetzt ist, aber.
Das ist sozusagen eine interne Funktion, die halt zurückgegeben wird.
Und die halt, das ist ja auch so der Trick, wie man das hinkriegt, dass der Scope, dass man halt auf die Sachen zugreifen kann, die im Scope der Funktion sind, dass man halt sozusagen das ist zu kompliziert, das kann man alles nicht so, das ist auch nicht empfängermäßig, das kann man nicht gut erklären.
Muss man sich einfach mal, also ich würde sagen, also ein Tipp ist, sich das, wenn man, wenn man Dekoratoren schreiben will, aus den Fangtools die Wraps-Funktionen zu nehmen und ja, einfach mal so ein bisschen damit rumzuspielen.
Man braucht ein bisschen, bis das irgendwie, äh, bis man das so raus hat.
Ja.
Genau, aber dafür sind Dekoratoren da.
Man kann damit ganz nette Sachen machen, wie zum Beispiel, also wenn man einfach nur wissen will, wofür braucht man solche Sachen eigentlich.
Wenn man ja zum Beispiel eben wieder Datenbankgeschichte, kann man sagen, okay, gibt es einen Transaktionsdekorator.
Da schreibt man halt einfach drüber.
Transaction Atomic.
Genau.
Das hier ist jetzt alles in einer Transaktion und alle Schritte gehen zusammen gut oder gar nicht.
Und wenn halt zwischendurch irgendwas nicht funktioniert hat, dann rollt das automatisch die Datenbank in den ursprünglichen Zustand zurück, als wäre nichts passiert.
Das ist ein tolles Beispiel, weil da gibt es nämlich auch den Kontextmanager.
Man kann auch sagen, with Transaction Atomic.
Ja, ja, ja, genau.
Ja, es ist klar, kann man auch machen.
Ja.
Das ist eine Geschichte.
Ansonsten, ja, man kann auch Dekoratoren dafür benutzen, um sich jetzt eine bestimmte Datenbankverbindung immer reinzuholen in eine Funktion.
Also wenn wir jetzt gerade über Dango reden, dann wird das ja auch benutzt, zum Beispiel für Funktionen zu dekorieren, Login required, dass man halt irgendwie eingeloggte Benutzer sein muss.
Das heißt, die Frage ist halt, was er dann macht.
Das kann man auch als Mix-In benutzen, das heißt, auch das wäre eine ähnliche Methode.
Ein Mix-In ist eine Subklasse, einer Klasse, die man benutzt, um bestimmte Attribute zusätzlich dazu zu tun.
Mixins sind so ein bisschen eben, wie man Code wiederverwenden kann, in Klassen, ohne erben zu müssen, weil Erben macht natürlich das sozusagen ein ganz klassische Weg und das kann man natürlich auch tun.
Ja, also in gewisser Weise ist ja eine Form von Vererben, also aber eine generalisierte Form, die irgendwie jetzt nichts genau mit der ursprünglichen Klasse zu tun hat, sondern.
Ja, genau, also du kannst halt, es ist nicht so, dass du zwei unterschiedliche Klassen, die nichts miteinander zu tun haben, an ganz unterschiedlichen Stellen in der Klassenhierarchie sind, können halt das gleiche Mix in verwenden, um zu.
Das ist cool, das ist so ein bisschen wie Genetik, du kannst dem Frosch Flügel geben oder so.
Ja.
Ja, ja, warum auch nicht.
Ja, wenn man Sachen hast, die Flügel haben wollen.
Man hat irgendwie eine Klasse, die Flügel bereitstellt, dann kann man diese Flügel jeder Klasse geben und die.
Ja, macht natürlich auch nicht immer irgendwie Sinn, aber Vererbung ist auch so eine problematische Geschichte.
Also es ist immer das, was einem, wenn man sich mit objektorientierter Programmierung beschäftigt, irgendwie so gesagt wird, wie man das tun soll oder so am Anfang, keine Ahnung, jedenfalls verbindet, ist es mittlerweile auch besser geworden, dass man halt Sachen von Dingen dann erbt, dass man halt, keine Ahnung, ja, weiß ich nicht, da wird immer mit solchen Beispielen gearbeitet, was hat man, dass man irgendwie, keine Ahnung, meistens irgendwelche geometrischen Formen oder sowas, ne?
Irgendwie, wenn man jetzt ein rechtwinkliges Dreieck hat, dann ist das auf jeden Fall schon mal ein Dreieck, ne?
Ein Dreieck ist irgendwas, was halt irgendwie.
Ja, ich finde das ganz schlecht, das nämlich dem Radius auch vorzustellen.
Also geometrischer Formen sind halt ganz okay, aber vielleicht auch mit dieser Universumsgeschichte.
Du hast irgendwo ein großes schwarzes Loch, so den Urknall oder sowas, und ein Objekt orbitet da irgendwie herum.
Das ist jetzt vielleicht schon mal so eine Galaxie.
Und dann, das ist halt die Subklasse, wäre es halt Universum, ne?
Das war die Basisklasse, von der alles irgendwie erbt.
Alles ist irgendwie so ein Ding.
Das ist ein bisschen groß.
Ja, hast du halt eine Galaxie, ne?
Das ist halt schon mal das erste kleine Ding.
Oh, okay, eben in der Galaxie gibt es ein Sonnensystem.
Ein Sonnensystem ist auf jeden Fall Teil einer Galaxie.
Da gelten halt die gleichen Gesetze, physikalischen Gesetze.
Und du hast ein Sonnensystem, hast du einen Planeten.
Das ist jetzt vielleicht schon unsere speziellere Klasse.
Und dann weißt du halt, genau, das gibt verschiedene Sonnensysteme, die haben vielleicht gleiche Grundlagen und Planeten können jetzt aber verschiedene Dinge besonders machen.
Ja, aber ich glaube, ich fürchte, also dass das wird auch, also mit solchen Dingen, genau, dass Leute versuchen, da irgendwie so Alltagsontologie irgendwie so.
Ja, aber das ist ja auch
passt ja schon.
Weil dieser Planet, der orbitet ja diesem Stern.
Und der Stern, der orbitet ja dem Zentrum dieser Galaxis so.
Ja, da wäre sozusagen die allgemeinste Oberklasse wäre sowas wie Himmelskörper oder sowas.
Oder keine Ahnung.
Nee, nee, nee, nee, nee, nee, nee.
Ich glaube, das ist gar nicht so.
Also Himmelskörper Objekt, ich weiß nicht.
Da brauchst du ja schon ein Orbit, das ist ja grundsätzlich.
Ja, aber ich würde nicht.
Ich muss die Erbung so ein bisschen gucken, oder?
Ich sehe, dass das immer wieder passiert und dass solche Leute, dass das versucht wird, das so zu beschreiben und ich finde, das ist nicht hilfreich, weil.
Du machst ja irgendwie immer so eine Basisklasse, ja und die Basisklasse vom Mond wäre jetzt ja Planet.
Die Basisklasse vom Planeten wäre das Sonnensystem, die Basisklasse vom Sonnensystem wäre dann das Universum, die Basisklasse von dem Universum wäre dann vielleicht irgendwie, ne?
Ja, nee, genau solche Sachen will man eigentlich nicht machen.
Also das ist genau das, was nicht.
Also das ist halt, ja, das klingt so ein bisschen danach, als würde das, aber ich würde das nicht versuchen, so auf die Alltagswelt zu applizieren, sondern es geht tatsächlich darum, dass man Sachen programmieren kann.
Und das ist, das ist oft nicht so wie, das ist halt anders.
Das ist nicht so wie die Welt da draußen.
Das ist schwer.
Oder so oft ist es nicht so, dass man die Welt da draußen modellieren muss und dann das, was man modellieren muss, ist ganz anders als das, was man so draußen normalerweise, man versucht, diese Analogien, die gehen immer so ein bisschen ins.
Ich habe da Schwierigkeiten mit.
Und ich finde, man kann sich das anders besser merken.
Wenn man jetzt, also hier, ich würde sagen, vererben sollte man einfach eher nicht machen.
Lieber nicht machen.
Also es gibt Fälle, wo das richtig und wichtig ist, aber diesen selten.
Und was einem aber erklärt wird, ist, dass das der Normalfall, so macht man das halt.
Dann würde ich sagen, das ist ganz falsch.
Nein, so macht man das eigentlich nicht.
Also Vererbung, es gibt Fälle, wo das geht, wo man das sinnvoll ist, aber das ist nicht so, dass man das immer machen oder normalerweise so machen sollte.
Sondern es ist halt eher die Ausnahme.
Normalerweise sollte man, wenn man zum Beispiel Code in zwei Klassen wiederverwenden will, dann macht man halt Mix hin.
Und nicht diese Vererbung.
Weil das ist halt, das ist auch am Anfang, das geht ganz gut, sobald es komplizierter wird, hat man da große Probleme, weil du dann, deine Hierarchie, die muss halt einfach stimmen, die muss halt passen auf dein Problem.
Das kannst du hinterher nicht mehr gut ändern und hinter gut anpassen, es geht alles nicht so richtig schön.
Und am Anfang zu sehen, wie das richtig wäre für das Problem, was man eigentlich lösen will, ist sehr schwer.
Ja, weil man
das Problem heißt noch gar nicht genau.
Genau, man kennt meistens das Problem nicht richtig.
Und bei Mixins ist es relativ simpel.
Das ist halt so wie, keine Ahnung, wenn ich nur, wenn ich ohne Objektorientierung programmiere, dann habe ich halt Funktionen, die ich aufrufe.
Und wenn ich jetzt merke, ich benutze den gleichen Code an drei, vier unterschiedlichen Stellen, dann mache ich halt eine Funktion draußen und rufe den an den Stellen, wo ich sozusagen das verwenden möchte, den Code einfach auf.
Anstelle, dass ich den Code da drin stehen habe.
Und genauso kann man das mit Klassen im Grunde auch machen.
Und Code, den ich in mehreren Klassen benutze, den ziehe ich halt in Mixins raus.
Und dann ist es relativ easy, weil ja, diese Mix-Ins machen halt nichts anderes, außer irgendwie halt eine Methode sozusagen hinzuzufügen zu einer Klasse.
Und ja.
Während so Vererbungen, hm.
Das macht halt mehr.
Das tut mehr.
Also es gibt halt dann diese Basis, ne?
Basisklasse, eine Basis oder sowas.
Oder dann gibt es noch sowas wie Message Resolution Order, MROs, wo man dann halt gucken kann, welche Methoden und welche Reihenfolge aufrufen werden, weil die sich ja gegenseitig überschreiben können.
Und das Problem, was man dann hat, irgendwann ist, dass wenn man da, wie du sagst, einen Feder macht, dann hat man Zirkelvererbung oder sowas.
Ja, das passieren halt, genau, wenn man irgendwas falsch macht, dann passieren unerwartete Dinge, die man auch nicht so, die nicht so offensichtlich sind.
Und ja, und es kann auch sehr schnell sehr hässlich werden.
Also es gibt wenig Fälle, wo das eine super sinnvolle Geschichte ist.
Das ist immer so, es ist halt so ein bisschen auch wieder wie bei den Dekoratoren, auch wenn man das am Anfang mal verstanden hat, wie das funktioniert.
Also ich meine, auch wenn man das mit der Vererbung verstanden hat, wie das funktioniert, dann ist das, dann fühlt sich das so toll an, dass man da ganz viel Dekoratoren machen will, ganz viel Vererbung und am besten das Ganze irgendwie in verschachtelte List-Comprehensions hackt oder so.
Mit abstrakten Metaklassen, bitte?
Ja, Metaklassen, oh ja.
Aber ich weiß nicht, vielleicht keine gute Idee.
Also jedenfalls nicht am Anfang.
Also wenn man dann irgendwann genau weiß, welches Problem man lösen möchte und möchte halt ein Framework bauen, das halt, wo man dann, also nehmen wir irgendwie sowas wie Django Rest Framework, finde ich das relativ gelungen.
Da kann man oft viel Funktionalität abbilden, dadurch, dass man jetzt sozusagen von irgendeiner, von irgendeinem Viewset oder so erbt und dann überschreibt man noch zwei, drei Methoden, passt ein bisschen was an und dann macht das ganz viel.
Sehr schön, aber dafür muss man sehr, sehr genau verstanden haben, welches Problem man hat.
Und wenn man so anfängt, dann üblicherweise landet man relativ schnell in einem ziemlich üblen Zustand.
Teufelsküche in der Schlangengrube.
Ja, genau.
Man kann das ja immer noch machen am Schluss.
Wenn man dann irgendwie wirklich verstanden hat, was man tut und so, dann kann man ja immer noch dann irgendwie Klassenhierchen bauen und so.
Aber am Anfang lieber nicht.
Ich glaube, das ist jetzt der richtige Ort für die nächste Frage.
Die wäre, was ist ein Monkey Patch?
Ja, das ist, da das alles Objekte sind in Python, kann man die natürlich und die alle dynamisch änderbar sind, kann man ja auch sozusagen einfach die Methode eines Objektes einfach, man kann ja sagen, zum Beispiel, wenn ich ja nicht nur Attribute setzen, sondern ich kann auch die Methode einfach überschreiben.
Ich könnte zum Beispiel sagen, wenn ich meinen Barbaren habe, von dem wir eben geredet haben, und er hat ein Attribut, das heißt Attacke und da ist immer irgendwas drauf, dann kann ich einfach die überschreiben.
Dann macht er bei der Attacke irgendwas anderes, zum Beispiel haltig oder so.
Genau, genau.
Und ich könnte einfach sagen, ja, Barbar.attack gleich Lambda XYZ, was auch immer da übergeben wird.
Das wäre zum Beispiel eine Möglichkeit, wie man Vererbung bei Klassen richtig macht, indem man die Basisklasse hat, die wäre jetzt wahrscheinlich in so einem Rollenspiel sowas wie eine Person und dann vererbt man dann auch verschiedene, weiß ich nicht, Rassen, zum Beispiel Echse oder Mensch oder sowas.
Nee, ich finde da sehr vorsichtig.
Und dann hat man dann Klassen, die man dazu macht, also zum Beispiel Magier oder Barbar.
Und dann kann man zum Beispiel Attacke oder sowas.
Überschreibt man dann.
Ja, aber das ist halt sehr verführerisch, dass man halt ein Bild davon hat, wie das, äh, wie sozusagen die Welt, die man im Spiel bauen will, aufgebaut ist.
Aber tatsächlich ist das zu programmieren oft was anderes, als nur diese Welt zu modellieren.
Und dann, das ist nicht das Kleise.
Oder jedenfalls meine Erfahrung ist so, dass wenn man das so versucht zu modellieren, wie man sich das vorstellt, dann passt es nicht so gut auf das, wie man das programmieren will.
Sondern es ist halt einfach, ja, es ist.
Aber das zu verstehen, das ist vielleicht fierig.
Also für jemanden, der das nicht weiß, warum, wieso, warum man das dann einfach nicht macht, obwohl das ja so intuitiv endlich so einen Zugang dazu gibt.
Ja, genau, also ich gibt da auch immer diesen Spruch.
Es gibt für jedes Problem eine Lösung, die ist einfach, leicht zu verstehen, elegant und falsch.
Das ist halt auch einmal, und was mich ärgert so ein bisschen ist, dass es halt auch immer so Programmierlehrbüchern oder so oft so, oder schlimm ist es, wenn Leute programmieren erklären und dann vielleicht gar nicht selber so da drin stecken, dann machen die das oft so.
Dann fangen die an, mit irgendwelchen Analogien aus dem täglichen Leben zu kommen und dass man halt so das abbildet, das ist aber, ich weiß nicht, ich, da liegt kein Segen drauf.
Das funktioniert so nicht.
Ja.
Naja.
Also ihr seht schon, wenn ihr über die Schlangengrube drüber wollt, dann ist er manchmal so ein bisschen, ja, Indiana Donze hängt von der Decke herüberschwingen, ju.
Ich würde, so als so Ratschlag wäre halt eher, es versuchen einfach zu halten, nicht zu komplizierte Sachen.
So ganzen komplizierten Sprachfeature sind vielleicht nicht so viel zu verwenden.
Oder das ein bisschen hinauszuzögern.
Ja, ich verstehe natürlich, dass das immer so ein bisschen auch reizvoll ist, aber nicht irgendwie so, wenn so Dinge, die so aussehen, als wie die Weltformel, die alles löst.
Sehr skeptisch zu sein.
Ja, dann machen wir direkt wieder mit einfachen Dingen weiter.
Was ist denn denn Argumente oder Keyword-Argumente?
Was sind Args und Quarks?
Ah, ja, ja, ja.
Das ist auch etwas, was immer ein bisschen verwirrend ist.
Ja, also Funktionen, Methoden haben Argumente, das heißt Dinge, die man übergeben kann.
Ganz normale Positionsargumente sind halt sozusagen das übliche irgendwie, die haben halt eine feste Stelle und werden dadurch dann identifiziert, dass sie halt an der ersten, zweiten, dritten Stelle oder so stehen.
Und dann gibt es halt noch Keyword-Argumente, wo man dann explizit dazu sagt, welches Argument man denn jetzt gemeint hat.
Das schreibt man dann halt sowohl in die Funktionsdefinitionen rein, als auch dann, wenn man es übergibt, wobei man es beim Übergeben nicht unbedingt braucht.
Also da ist es dann halt so, wenn man das weglässt, dann wird halt das nächste Keyword-Argument genommen.
Das ist so ein bisschen, da können dann komische Sachen passieren.
Und dann ist es auch so, dass man, wenn man sich, wenn man jetzt eine Liste von Argumenten übergibt, dann kann man die natürlich alle einzeln übergeben, man kann die aber auch insgesamt übergeben.
Mit Sternchen dann bei Argumenten.
Oder mit Sternchen, Sternchen bei Keyword-Argumenten.
Also wenn man die Liste hat in der Hand, wenn man eine Liste hat oder Toupel, dann kann man einfach einen Stern davor schreiben und dann wird das automatisch sozusagen als Argumente dann übergeben.
Das heißt, man hat.
Man sagt dann irgendwie Funktion, Klammer auf, Stern und dann eben Args, Argumente oder wie auch immer das, die Items, die Struktur heißt, die man jetzt gerade in der Hand hat, Klammer zu und dann kann man in der Funktionsdefinition drin stehen haben, sowas Dev-Funktion, Klammer auf, A, B, C und ja, muss dann natürlich alles irgendwie stimmen von der Anzahl und so, aber das passiert dann automatisch.
Be Keyword-Argumenten relativ nützlich, weil da kann man alle viele Sachen, die man irgendwie zugewiesen hat, irgendwie an eine Liste packen und dann kann man die einfach alles mit Sternchen, Städtchen übergeben, halt dann seine Keywords.
Genau, das eben bei normalen Positionsargumenten ist es halt, entweder man übrigens sie per Position oder Stern.
Kann auch eben in der Funktionsdefinition sagen, so, das können jetzt hier beliebig viele sein, dann schreibt man halt nicht A, B, C rein, sondern Stern-Args, und dann da kommen dann halt beliebig viele Argumente rein, die dann hinterher in der Liste Args sind.
Wenn man, vielleicht kennen Leute das noch von Pearl oder so, gibt das nur so.
Es geht in Python auch.
Ist da aber ein Spezialfall.
Oder genau, und das Ganze geht mit Keyword-Argumenten ganz genauso, nur dass es dann halt nicht Stern ist, sondern Sternstern.
Und damit lassen sich halt sehr, sehr leicht zum Beispiel Dikts in Keyword-Argumente verwandeln und Keyword-Argumente in Dikts, was halt manchmal sehr praktisch ist.
Und einem viel Schreibarbeit erspart.
Ja.
Cool.
Jetzt haben wir noch zwei Sachen, die hier noch ein bisschen in diese Funktionen reingehen.
Einmal, wir haben ja Funktionen, jetzt jede Menge so Sachen.
Dann, was ist eine Lambda-Funktion?
Was macht die denn dann?
Haben wir, glaube ich, auch schon mal einmal kurz besprochen, aber.
Ist eigentlich nichts Besonderes.
Es ist eine Funktion wie jeder andere.
Also was halt in Python nicht so richtig schick geht, ich mache ja auch ein bisschen JavaScript und das ist da so schon ein Stückchen eleganter vielleicht.
Oder was es in Python so nicht gibt, sind so anonyme Blöcke oder anonyme Funktionen über mehrere Zeilen oder sowas.
Sondern da gibt es halt Lambda, also der.
Warum muss
das überhaupt sein?
Wofür braucht man sowas am Ende?
Ja, es gibt oft irgendwie Situationen, wo man eine Funktion übergeben möchte irgendwo hin, aber die sonst nicht braucht.
Also ein Beispiel wäre jetzt irgendwie, wenn man irgendwas mit NumPy-Arrays macht oder so oder Data Frames.
Da ist es ja so, dass man eigentlich keine Vorschleifen, nicht per Vorschleife über irgendwas iterieren kann, weil Vorschleifen super langsam sind in Python.
Was jetzt nicht heißen soll, dass man nicht vermeiden.
Also Vorschleifen sind halt schon gut, aber wenn man jetzt über ein Array mit irgendwie ein paar Millionen Einträgen iteriert, dann will man das vielleicht nicht als Vorschleife hinschreiben, sondern was man dann hinschreibt, ist halt irgendwas dataframe.apply und dann übergibt man eine Funktion, die dann halt das macht, was man jetzt eigentlich im Body einer Vorschleife gerne gemacht hätte, ab die man ja nicht hinschreiben kann.
Diese Funktion hat aber sonst keinen Zweck.
Die ist nicht, an anderer Stelle braucht man die nicht, weil eigentlich, was man hätte hinschreiben wollen, wäre eine Vorschleife gewesen und dann das, was man in dieser Vorschleife macht, halt machen.
Aber das geht halt nicht.
Daher braucht man halt jetzt diese temporäre Funktionen, der man jetzt auch gar nicht unbedingt einen Namen geben will.
Man möchte halt quasi die Quadrate haben von einer Spalte oder sowas.
Irgendwie sowas oder rechnet halt irgendwas aus auf jedem Element oder so.
Und dann, genau.
Lambda gibt halt sozusagen, also Lambda X, Doppelpunkt X zum Quadrat oder sowas, würde halt ein Argument nehmen und dieses Argument mit sich selbst multiplizieren und dann wieder zurückgeben.
Dass man halt das Return weglassen muss, also Return kann man nicht hinschreiben in der Lambda, sondern es ist halt das, was halt man, das letzte, was irgendwie.
Es ist implizit, nicht explizit an.
Implizit wird das halt einfach zurückgegeben.
Und ja, auch die Argumentübergabe ist ein bisschen anders.
Es ist halt nicht irgendwie Klammer auf und dann irgendwas, sondern es ist halt einfach Leerzeichen und dann Liste der Argumente, Doppelpunkt.
Und das wird halt implizit passiert.
Das ist halt.
Und es kann alles nur in einer Zeile stehen.
Es darf nicht mehrere Zeilen.
Aber so ein bisschen hässlich ist es.
Es ist ein bisschen hässlich, ja.
Auf der anderen Seite ist es so, wenn das komplizierter wird, man muss das ja nicht so machen.
Man kann auch tatsächlich eine Funktion hinschreiben, die man einfach irgendwie nennt.
Man kann ja auch sagen, irgendwie rechne mir irgendwie das Quadrat aus oder so Funktionen.
Und dann schreibt man halt in diese Funktion, dann kann man ja auch mehrere Zeilen schreiben, die schreibt man dann da rein und dann übergibt man das Ding halt.
Der Lambda-Funktion.
Nicht der Lambda-Funktion, sondern übergibt das statt der Lambda-Funktion, weil es ist genau das gleiche.
Es ist halt, das, was man zurückbekommt von diesem Lambda, ist das.
Das heißt, Lambda braucht man eigentlich überhaupt nicht und weil das da irgendwie die Kinder ist.
Nee, man braucht es nicht.
Ist es halt manchmal auch nett, das so hinschreiben zu können, aber wirklich brauchen tut man es nicht.
Es spart ein bisschen Schreibarbeit für zum Beispiel so einfache Operationen wie einfach Quadratik geben, dann kann man einfach das Lambda in die Zeile schreiben, wenn man es nicht wieder sonst braucht, dann.
Genau, weil du hast halt, wenn du Funktionen hinschreibst in Python, immer einen gewissen Zeilen-Overhead, weil, naja, da die Umbrüche syntaktisch relevant sind und die Eindrückungen, ist es halt so, dass du da auf jeden Fall immer mehrere, mindestens mal zwei Zeilen hinschreiben musst.
Ja, und mit Lambda kannst du es auch in einer Zeile hinschreiben.
Und wenn das wirklich eine ganz simple Geschichte ist, dann willst du vielleicht keine, nicht deswegen eine Funktion definieren, sondern ja, aber letztlich kann man dafür auch ganz normale Funktionen verwenden.
Und was ja on Python auch geht, was auch schön ist, du kannst halt innerhalb von Funktionen auch wieder Funktionen definieren.
Also du musst ja nicht die Funktion dann außerhalb der Funktion.
Das heißt, du kannst die Funktion auch direkt da an die Stelle schreiben, wo du sie verwenden willst.
Wann macht man das denn, dass man so schachtelte Funktionen macht?
Ja, eben, zum Beispiel, wenn du halt eine Funktion sonst nirgendwo verwenden möchtest und möchtest halt, aber du brauchst eine Funktion.
Da sind wir wieder bei zum Beispiel bei Closures, brauchst du das halt, wo du dann eine Funktion zurückgibst, die halt Zugriff auf den Scope, auf Variablen hat, die im Scope dieser Funktion liegen.
Ja, also wenn du also Closure ist quasi, sozusagen du hast eine Funktion und in dieser Funktion gibst du jetzt, du gibst jetzt eine andere Funktion zurück.
Eine innere Funktion sozusagen.
Und du möchtest, dass diese Funktion Zugriff hat auf eine Variable, die zum Beispiel innerhalb der äußeren Funktion definiert ist.
Zum Beispiel ein Counter, der mit irgendwas initialisiert wird.
Also genau, das Beispiel können wir mal nehmen.
Sagen wir mal Zähle ab, Klammer auf, x, Klammer zu, Doppelpunkt Counter gleich X und dann Def inner, Klammer auf Y, Klammer zu, Doppelpunkt und dann Return Range
Counter, die Hälfte der Höhre hat auf Counter, Y oder so.
Es geht darum, sozusagen, wenn du sagen möchtest, ab wann etwas zählen soll, dann möchtest du diesen Counter ja diesen State wieder halten irgendwo.
Und du möchtest ihn irgendwo halten, wo jetzt die innere Funktion, die du zurückgibst, die jetzt dann irgendwie zum Beispiel irgendwas iteriert oder so, drauf zugreifen kann.
Aber du willst es sonst nicht manipulierbar haben.
Das ist auch eine, damit kannst du tatsächlich dann auch Werte so wegverstecken, dass man da nicht mehr rankommt.
Jedenfalls nicht.
Also man kommt schon, aber dann wird es schwierig.
Nicht mehr so einfach.
Und ja, dafür braucht man zum Beispiel so innere Funktionen.
Ohne die ginge das gar nicht richtig.
Also, und das nennt man, das ist eine Clojure.
Also, dass sozusagen die innere Funktion hat Zugriff auf den Counter, den ich irgendwann mal übergeben habe.
Aber weil die innere Funktion ja im gleichen Scope ist wie das Ding, wie das, was ich ursprünglich mal gesetzt habe.
Ansonsten komme ich da von außen aber nicht mehr ran.
Wenn ich jetzt nur die zurückgegebene Funktion habe, dann komme ich an den Counter-Wert nicht mehr ran.
Und dann kann ich halt die äußere Funktion verwenden, um zu sagen, gib mir einen Counter, der ab 5 zählt immer.
Oder gib mir einen Counter, der ab 10 zählt immer.
Und das 10 oder 5 steht dann halt eben in dieser, ja, ja, ist ein etwas komplizierteres Konzept, muss man.
Aber das ist halt auch die Art, wie dann irgendwie die Kuratoren und Kontextmanager und so funktionieren.
Die machen da Dinge in der Richtung.
Ja.
Genau.
Aber das ist eigentlich, das finde ich auch Python sehr schön, dass man halt in Funktionen auch locker irgendwie Funktionen definieren kann.
Man kann auch Klassen innerhalb von Klassen definieren und so.
Also das geht einfach problemlos.
Klingt nach viel Konfusion für die Anfängerhöhre, die jetzt gerade da.
Ja, ja, vielleicht sollte man, genau, auch wieder.
Nee, vielleicht sollte man das mal noch nicht machen.
Ja, also ich habe jetzt noch eine Basisfrage.
Was ist der Unterschied von einer Zuweisung von gleichgleich oder ist, also nicht zugleich, sondern einer Abfrage.
Man würde etwas vergleichen und ein gleich gleich oder ein ist.
Also zum Beispiel A, gleich gleich B, A ist B, etwas ist gleich gleich none, ist nun.
Ja, also wenn ich gleich gleich verwendere, also gleich ist natürlich irgendwie Zuweisung, aber gleich gleich, da wird halt der Wert verglichen.
Also und bei is wird verglichen, ob es das gleiche Objekt ist.
Und deswegen sag ich man zum Beispiel bei None sagt man immer is none, weil es nur ein None-Objekt gibt.
Genau, none ist ein Singleton.
Und deswegen kann ich halt so testen, ob es wirklich None ist.
True und Falls sind auch Singleton.
Ja, bin ich mir jetzt nicht so ganz sicher, aber ich glaube schon.
Ich weiß aber nicht genau.
Ja, es müsste wahrscheinlich so sein, ne?
Das könnte eigentlich gar nicht anders.
Okay, das heißt, ihr müsst halt tatsächlich, wenn er ist, ist immer genau das Objekt.
Das heißt, man kann es nicht so gut.
Ja, ja, aber man kann es auch zuweisen.
Also es ist auch ganz böse.
Man kann true und false auch noch anders belegen.
Also müsste man mal nachgucken.
Ja, was irgendwie spannend ist, weil jetzt, wir haben ja so ein paar Mal über so Sachen geredet, was jetzt irgendwie Klassen sind und Objekte und Typen, dass alle Sachen ein Python irgendwelche Objekte sind, irgendwelche Typen sind.
Und dann habe ich mich irgendwie gefragt, ob jetzt nicht die ganzen zuweisen.
Also man kann es irgendwie Typen umwandeln, ja, also ne, von einem Integer auf String oder sowas, ob das nicht halt auch ein Klasse dann eigentlich ist, die man halt nimmt, weil das halt ein Typ ist und ein Objekt ist, deswegen müsste es eigentlich groß geschrieben werden, weil man halt eine Instanz eines Objektes ändert und eine Instanz eines Objektes erzeugt.
Zum Beispiel von einer Instanz eines Objektes String, einer Instanz eines Integer wechselt.
Wenn man ein Inter vorstellen müsste, müsste ein großes Int sein, dann an der Stelle irgendwie war ich ja ein bisschen verwirrt.
Ja, also da, ich rate jetzt mal, woher das kommt.
Ich weiß es ehrlich gesagt auch nicht so genau.
Vielleicht weiß das jemand besser und kann mich da korrigieren, aber ich denke mal, es liegt daran, dass das Build-Ins sind.
Also ja, eigentlich die Konventionen im Platten ist so, wenn das eine Klasse ist, dann schreibt man das halt groß.
Aber ich glaube, alle Build-Ins sind klein.
Und da das Build-Ins sind.
Sagt man eher, das ist wichtiger, weil es gibt nicht so viele Bild-In.
Aber richtig wäre es tatsächlich, dass man, wenn man, zum Verständnis vielleicht, dass man irgendwie, wenn man einen Typ ändert, einer Variable beispielsweise, dass man einen neuen Instanz, einer neuen oder einer anderen Klasse erzeugt.
Ja, ja, das ist so.
Aber das passiert auch tatsächlich.
Also wenn ich sage, int Klammer auf 5, Klammer zu, dann wird ein neues Integer-Objekt erzeugt.
Genau, mit dem Word 5.
Also es ist tatsächlich, ja, auch Dikt ist ja eine Klasse tatsächlich.
Ich kann ja auch davon erben und so, sollte ich vielleicht nicht machen, aber auch da, aber ich kann davon erben und das funktioniert auch.
Aber ja, ich denke, es hängt damit zusammen, dass die Build-Ins halt so Spezialfälle sind.
Wenn ich die Klassen verwenden möchte, für die ganzen Dinger gibt es auch noch richtige Klassen.
Zum Beispiel für Dikt und List und so gibt es User-Dickt, User-List.
Und auch wenn ich jetzt irgendwie selber ein eigenes Dikt, das ein Dinge ein bisschen anders macht als normales Dikt verwenden möchte, dann sollte ich halt irgendwie von User-Dikt erben und nicht von einfach nur kleingeschrieben dickt.
Weil sich schon Leute rumgekümmert haben, bestimmte Probleme zu umgehen, auf die man dann stößt, wenn man das
nicht macht.
Ja, genau, genau.
Ja, jetzt haben wir ja, wir haben noch jede Menge.
Ich weiß gar nicht, ob wir das heute in der Erfolge alles irgendwie unterkriegen.
Noch ein Nuss hat er gefragt, was denn eine Shadow Copy ist.
Also warum man.
Wie arbeitet man richtig mit Listen im Zusammenhang Funktionen?
Gibt man eine Kopie und returnt eine neue Liste oder gibt man eine Liste und ändert die quasi in Place?
Was hat das damit zu tun?
Ja, das ist halt auch eine eher auf unter Umstände Zielfrage, was man da machen möchte.
Also einmal, vielleicht zuerst das mit der mit der Shallow-Copy, also die Frage ist, was passiert eigentlich, wenn ich jetzt sozusagen eine Kopie von irgendwas machen möchte und weil ich warum auch immer irgendwie eine zweite Version von irgendeiner Datenstruktur brauche oder so.
Da ist es, wenn ich jetzt die einfach nur kopiere, also wenn ich jetzt, also in Python habe ich eigentlich mal Referenzen auf solche Datenstrukturen in der Hand.
Also auch die Übergabe von Sachen ist immer bei Referenz, also es gibt es ja ein C, es ist unterstellt ein anders, da gibt es halt, kann ich Argumente übergeben als Referenz oder halt als Wert, ja, also direkt den Wert einfach so.
Und in Python ist es immer per Referenz.
Also in der Variable, die ich übergebe, steht immer sozusagen einfach eine Speicheradresse drin, die halt auf das Objekt zeigt, das ich übergebe.
Und ich übergebe immer nur die Adresse.
Ich übergebe nicht der Funktion das Objekt selbst.
Und jetzt ist es halt so, wenn ich einfach nur bestimmte Operationen duplizieren mir halt jetzt diese Adresse, aber nicht den Inhalt dahinter.
Das heißt, wenn ich jetzt, ich mache eine Kopie davon, müssen wir überlegen, in welchen Umständen ich das hinkriege.
Wenn ich jetzt einfach nur Copy vom, ich weiß nicht, ob Copy in Bildinnen ist, aber wenn ich einfach nur sage, kopier mir das mal, dann kann es sein, dass mir nur die Referenz kopiert wird.
Das heißt, mir wird halt die Speicheradresse in eine andere Variable kopiert, aber wenn ich jetzt irgendwas am Inhalt einer Liste oder so ändere, dann ist das in beiden Listen geändert.
Und das ist unter Umständen nicht so intuitiv.
Vielleicht.
Hätte man jetzt nicht so mit gerechnet, sondern man hätte damit gerechnet, dass ich jetzt zwei Listen habe, die im Hauptspeicher an zwei unterschiedlichen Stellen liegen.
Und eine Shallow-Kopy ist halt eine, die nur die sozusagen, also bei einer Liste könnte ich jetzt mir sogar vorstellen, dass es oft, wenn ich jetzt nochmal List drum herumschreibe oder so, dass er dann tatsächlich eine Kopie erzeugt wird.
Also eine nicht Shallow-Kopie, aber wenn ich jetzt eine komplizierte Datenstruktur habe in irgendeinem Dikt oder so, wo viele Sachen ineinander verschachtelt drin liegen, dann ist es so, wenn ich jetzt sage Dikt von dem Ding, dann ist es eine oder wenn ich sage Copy, dann ist das eine Shallow-Kopie.
Und sozusagen.
Warum brauche ich denn überhaupt eine Shallow Kopie?
Dann könnte ich auch einfach auf das normale Dikt zeigen, wenn das eh noch das gleiche Epack zeigt.
Also eigentlich eine andere Benennung.
Wenn ich die Inhalte mitkopieren will, oder dann gibt es zum Beispiel eine Funktion aus dem Copy, ich glaube, das ist Standardbibliothek.
Dann sagt man immer Form Copy, Import Deep Copy und dann sagen Deep Copy, irgendwie komplizierte dickt verschachtelte Datenstruktur und die geht dann rekursiv da durch und kopiert den ganzen Kram daraus in eine andere Datenstruktur.
Und dann habe ich halt das tatsächlich getrennt voneinander.
Aber ansonsten ist das halt nicht so einfach.
Wenn ich da Dikt drum herum mache, dann kann es zwar auch sein, dass es ein neues Dikt ist an einer anderen Speicheradresse und dass ich die Keys und Values kopiert habe, aber die Values waren halt Referenzen auf irgendwas und die Objekte hinter diesen Referenzen haben sich halt nicht geändert.
Und das kann halt sehr.
Da kann man das so ein bisschen mit an Fuß schießen, wenn man sowas übergibt wie leere Listen als Standardwert vom Keyword.
Ja, da kann man sich böse in den Fuß schießen mit.
Weil dann, also das ist, glaube ich, generell das Problem.
Also bei so ein paar Sachen, die man als Keyword setzt, ja, wenn man das irgendwie eine Funktion hat, da wird ein Keyword übergeben, das setzt man einem Default-Wert, indem man es zum Beispiel an der leere Liste hätte oder einen random initialisierten Wert oder sowas.
Der wird halt beim ersten Mal dann initialisiert und er steht dann halt aber in der Speicheradresse dieser Wert drin, der dann halt dem zugewiesen ist schon, weil das halt dann nur darauf zeigt und halt nicht jedes Mal ein neues Objekt generiert.
Und das heißt, man hat immer dieselbe leere Liste, die dann vielleicht nicht mehr leer ist, nachdem man die Funktion einmal aufgerufen hat und dann.
Und dann ist es immer die gleiche und dann funktioniert das sogar oft und dann irgendwann fällt es einfach ganz furchtbar auf den Fuß und man weiß nicht genau.
Ja, also das, da an solchen Problemen habe ich auch schon lange rumgedebugt, bevor ich mir dann so, oh nein, das ist immer die gleiche Liste, aber scheiße.
Und da ist da auch da eine Konvention, dass man das eben eigentlich, dass man nicht als Default-Argument in eine Funktion reinschreibt, irgendwie Default gleich Klammer auf, Klammer zu oder so.
Man sagt immer None und dann macht man und dann macht man
eine Überprüfung, ob es None ist und dann setzt man die Liste neu.
Das ist halt echt nur eine böse Fußangel, ja.
Also das ist, das kann einen schwer erwischen.
Ja, bei random Werten übrigens genau dasselbe.
Also wenn ihr jetzt irgendwo so einen Zufallswert generieren lassen wollt, wie vom Random 1 bis 10 oder sowas und dann habt ihr den einmal installiert, der gibt nicht jedes Mal, wenn ihr die Funktion aufruft, einen Defort neuen Zufallswert
zurück, sondern
immer dasselbe.
Also das ist an der Stelle nicht intuitiv.
Also fand ich auch sehr komisch, dass er dann nicht einfach jedes Mal beim Aufrufen das neue initialisiert, sondern dass er halt dann die Objekte nimmt, die er einmal schon irgendwo liegen hat.
Ja, also wie man also eine Geschichte, wie man, also List-Comprension macht immer eine Kopie, wenn man zum Beispiel erzeugt immer eine neue Liste.
Ansonsten, ja, die Copy aus dem Copy-Modul, weil wenn es kompliziertere Datenstrukturen sind, dann muss man sich das nicht selber, also oft ist es ja, ist man es ja wirklich kompliziert, wenn man da halt was, ja, man muss halt rekursiv durchgehen und das will man ja vielleicht auch nicht selber schreiben.
Und da gibt es halt schon ein Ding für, das man da benutzen kann.
Dann ist es so, naja, was diese unterschiedlichen Stile angeht.
Also wenn man sich so ein bisschen anguckt, was in den, es gibt ja unterschiedliche Arten zu programmieren, ja, so imperativ.
Ich würde auch Pyth eher, auch wenn es auch mit Berechtigung sagen kann, ist es auch irgendwie eine funktionale Programmiersprache, ist es doch eher, die meisten Leute verwenden es halt irgendwie imperativ.
Und in dem Lager sozusagen Paradigma der funktionalen Programmiersprachen ist es aber eher so, dass man halt da und nicht nur da, das setzt sich auch in anderen Bereichen durch.
In JavaScript sehen wir das in letzter Zeit oft, auch wenn es um so State-Handling-Geschichten geht.
Da gibt es dann Redux und so, dass man, wenn man jetzt solche Sachen handelt, versucht immer nur mit Datenstrukturen zu arbeiten, die nicht veränderbar sind.
Also die immutable sind und immer nur Kopien erzeugt, wenn man irgendwas ändert.
Also man ändert nichts in einer bestimmten Datenstruktur, sondern man erzeugt eine neue Kopie und an der ändert man dann halt irgendwas, beziehungsweise man ändert nichts, sondern man baut es dann halt neu.
Was halt diverse sehr, sehr, sehr, sehr coole Nebeneffekte hat.
Unter anderem, dass ich Sachen dann perfekt parallelisieren kann, dass ich weiß, dass ich keine Seiteneffekte habe, dass ich super testen kann, es hat eine Menge, und immer wenn Leute, die aus so einer funktionalen Ecke kommen, sehen, was man so in Python imperativ macht, dass man irgendwie Attribute von irgendwelchen Objekten ändert oder halt irgendwie einen Dikt übergeben bekommt, das dann irgendwie ändert und dann, also würde man jetzt in funktionaler, in einer richtigen, ri
chtigen, funktionalen Programmiersprache würde man nie irgendwie einen Dikt oder eine Liste oder sowas in einer Funktion nehmen, da irgendwas dran ändern und das Ding dann wieder zurückgeben oder so oder am besten gar nicht zurückgeben, sondern einfach nur ändern.
Sondern man würde immer, wenn man was ändert, eine neue Kopie zurückgeben.
Weil man dann halt diese ganzen schönen Effekte hat.
Was, wenn man das nicht tut, was würde ich sagen, aber in Python oft so ist, dann übergibt irgendwo eine Liste und dann ändert man irgendwie ein Element in dieser Liste und dann gibt man die Liste wieder zurück, dann gehen ganz viele schöne Sachen nicht mehr, weil dann ist es halt, ja vielleicht irgendwas kaputt gemacht.
Ja.
Was auf der anderen Seite manchmal halt auch total viel einfacher macht, als wenn jetzt wenn man es funktional schreibt und auch effizienter, weil also einmal ist es so, man kann halt Dinge nicht mehr so richtig direkt beeinflussen und es ist halt so, man muss halt, wenn man alles immer kopiert und jetzt man aber jetzt große Datenmengen hat zum Beispiel im Data Science Bereich, ist es halt, wenn da deine Datenstrukturen alle hunderte Megabyte groß sind und du machst immer Kopien von allem, was auch, also tatsächlich, Pandas macht das auch per Default, wenn irgendwelche alle Operationen geben, immer Kopien zurück.
Aber das kann auch ganz schön in den Hauptspeicher gehen.
Manchmal muss man schon sagen, so, ja, hier bitte nicht kopieren, das geht einfach nicht, passt dann nicht mehr.
Und dann muss man halt Sachen direkt in place ändern oder so und das ist natürlich immer ein bisschen schmutzig, aber ja.
Quick and dirty, ja, ja.
Dunkle Magie wieder.
Ja, also hängt davon ab, würde ich sagen, dass man schon ein Problem hat.
Und also wenn man das nicht kennt, dann sich mal so anzugucken, wie man mit allen Datenstrukturen einfach nur immutable irgendwie hält und immer kopieren soll, das ist eigentlich schon die, die, die, das ist schon sehr schick, aber.
Also dann kommen wir direkt, das direkt an, was ist denn deine Lieblingsdatenstruktur?
Meine Lieblingsdatenstruktur, also ich tatsächlich, ja, dickt.
Hätte ich jetzt auch gesagt, früher fand ich das den ganz voll dickt, aber ich auch, also vielleicht mal gerade ist, ja.
Naja, aber also und vor allen Dingen ist die Dikt-Implementation in Python halt auch total super.
Also die ist richtig schnell, die ist halt sehr effizientes Ding.
Und ein Riesenhaufen Probleme lassen sich dadurch schon lösen.
Also wenn man das ordentlich verwendet, dann kriegt man da so einen sehr großen Teil der so 0815 Programmiergeschichten, die man so macht, kriegt man halt mit Listen und Dikts irgendwie abgebildet.
Listen braucht man auch, halt gerade wenn man irgendwann viele Dinge iteriert und so, aber Dikts ist halt, das Schöne daran ist, dass man halt irgendwie sozusagen beliebige Dinge irgendwie speichern kann.
Und man kann die Namen, unter denen man das findet, dann halt irgendwie dynamisch generieren und muss das halt nicht vorher definiert haben in Code.
Und wann nutzt man denn Tupels als Datenstruktur, wenn man eine Listen hat?
Also warum ist das überhaupt?
Ja, Tupel sind halt immutable, ja, genau.
Das ist halt der Grund, deswegen an den Stellen, wo man es halt immutable haben will, dann kann man die halt gut nehmen.
Unter anderem zum Beispiel, wenn du halt möchtest, dass etwas Key in einem Dikt sein kann.
Das geht halt mit einer Liste nicht.
Da musst du halt einen Tuppel nehmen.
Oder halt bei so Geschichten wie Tuppel-Unpacking und so, das geht auch nur mit dem Klartierung.
Das geht auch mit Listen.
Klar, das geht auch mit Listen, aber ich weiß, überlege jetzt gerade, ob es einen tieferen Grund gibt, warum Argumente ein Tuppel sind.
Also, ja.
Gell.
Also das
Dick-Key war vielleicht eine gute Idee, ja.
Es gibt schon den Fall öfter mal, dass man das halt nicht änderbar haben will und dann nimmt man halt einen Tuppel statt einer Liste.
Aber tatsächlich ist es so, es gibt auch skalare, sozusagen einfache Werte irgendwie, also sowas wie eine 5 oder String, wobei man muss man.
Listen und Dicts ist halt auch so das, was man in allen Programmiersprachen irgendwie oder allen vor allen Dingen allen Skriptsprachen irgendwie eingebaut findet, ja, das hast du halt auch in Pearl und in PHP und in JavaScript.
Die heißen halt in allen diesen Programmiersprachen irgendwie ein bisschen anders.
In Pearl heißt es halt Hash und Array, ja, in PHP heißt es Assoziatives Array und weiß ich nicht, JavaScript heißt es halt Object und ich glaube, da heißt es aber dann auch Array.
Ja, naja.
Aber diese Grunddatentypen hast du halt überall, deswegen, weil das ist halt, damit kannst du halt schon eine Menge machen.
Und Tuppel gibt es halt eigentlich, glaube ich, nur in Python und anderswo nicht, weil es auch sonst nicht so häufig verwendet wird.
Ist halt schon eher so ein bisschen Spezialfall.
Ja, es gibt auch oft von den ganzen, also was auch mittlerweile, glaube ich, ein integrierter Datentyp ist, ist halt Set in Python.
Das ist auch eine Datenstruktur, die man relativ häufig, oder ich benutze die relativ häufig.
Und von denen gibt es halt dann auch Immutable-Varianten.
Ich weiß jetzt gar nicht, ob es Immutable-Tickets gibt.
Aber zum Beispiel von Sets gibt es halt Frozen Set.
Eben auch für solche Fälle wie du möchtest, dass es irgendwie als Key entikt ist oder so.
Und den kannst du halt dann nicht mehr verändern.
Vielleicht gibt es auch sowas wie eine Frozen List, ich weiß nicht genau.
Aber Frozen Set benutze ich tatsächlich ab und zu.
Frozen List ist Tupel?
Ja, könnte sein, genau.
Frozen List ist Tupel, ja, genau.
Okay.
Wann nutzt man denn NumPy-Arrays?
Ja, immer dann, wenn man halt sozusagen so viele Daten hat, dass es irgendwie nervtötend wird, ansonsten.
Und wenn man jetzt die ganzen Spezialfunktionen vielleicht verwenden will, die halt auch in NumPy und so mit drin sind.
Ja, und genau, dann gehen halt die Sachen, die sonst lange dauern, halt einfach schnell und muss halt ein bisschen anders programmieren.
Es ist halt dann alles darauf ausgelegt, dass das vektorisiert wird und das heißt, Vorschleifen und sowas gehen eigentlich nicht mehr.
Und was natürlich ein bisschen sehr anders ist als das, was man normalerweise macht.
Aber ja.
Okay.
Dafür braucht man dann bei Lumper Rays, muss man dann mit Lambda arbeiten oder MR.
Ja, oder halt die Funktionen verwenden, die es schon gibt.
Das meiste gibt es ja, sozusagen, würde ich mal sagen.
Und dann ansonsten, wenn es das halt nicht gibt, dann genau, übergibt man halt eine Funktion.
Okay.
Wie seralisierst du denn denn Daten für Übertragungen?
Ja.
Kommt drauf an.
Also erstmal, was das überhaupt zu realisieren.
Realisieren ist halt in eine Zeichenkette umwandeln, dass man das irgendwo hinschicken kann.
Und dass wenn man dann weiß, was dahinter steckt, wenn man daraus wieder Objekte baut, mit denen man Dinge tut.
Ja, oder genau, ich würde sagen, man hat eine Datenstruktur und man möchte sie halt in irgendeine Form so verwandeln, dass man sie halt irgendwie über Netzwerke verschicken kann oder irgendwo hinspeichern kann und man lädt sie hinterher irgendwo wieder.
Man kann auch verfieren, dann kann man sie auch
abschreiben und hat die gleiche Datenstruktur wieder irgendwie.
Und das kann man natürlich, je nachdem wie kompliziert das ist, was man halt da ein- und auspacken möchte, beliebig kompliziert gestalten.
Also das, was heutzutage ganz oft verwendet wird, und insofern ist es auch keine so schlechte Wahl, das ist JSON wird halt oft benutzt.
Kannst du halt Sachen einfach nach JSON verwandeln.
Also alles, was irgendwie so Richtung Dickt ist oder verschachtelte Dicts und meistens hast du irgendwie Listen und Dicts irgendwie ineinander verschachtelt sozusagen als Datenstruktur.
Und das kannst du halt hervorragend irgendwie als JSON einfach verstanden.
Also auch mit Resident kein Problem, auch mit Tukeln kein Problem.
Daten, also Datums halt.
Datumsformate ist das halt halt blöd.
Genau, solche Sachen gehen dann schon nicht mehr so gut.
Also wenn jetzt ein Datum hast, dass du irgendwie oder einen Zeitstempel, irgendwie einen Zeitpunkt, wenn du den irgendwie in JSON speichern willst, dann ist halt blöd.
Also der Fluhrer von Datum ist Daten, ne?
Das ist aber gerade ein bisschen verwirrend, wenn wir über Datenschutz reden.
Aber ja.
Genau, das ist ein bisschen Kacke.
Und dann gibt es natürlich dann diverse ISO-Standards, wie man das dann doch irgendwie mit Zeitzone und keine Ahnung.
Und dann bist du aber darauf angewiesen, dass alle irgendwie die gleiche Idee davon haben, was denn jetzt in diesem String, der da in dem JSON steht, was das denn, was in der Element jetzt gemeint ist und das ist manchmal ein bisschen nervtötend.
Aber solange man nicht, also Datum ist immer etwas, was meistens dann Probleme macht.
Aber einfach so Listen, Dicts, Strings, das funktioniert ganz gut.
Und ja, also für diese einfachen Fälle ist JSON ganz gut geeignet.
Da da auch mittlerweile so viel verwendet wird, ist ja auch viel Arbeit reingeflossen, die Parser und Rausschreibdinger halt so schnell zu machen und das geht eigentlich alles ziemlich gut.
Es ist halt auch halbwegs sparsam, was halt sozusagen den Platz angeht.
Wenn du jetzt eben sowas wie XML nimmst, XML ist halt da, kannst du mehr mitmachen, aber es ist halt komplizierter, es sind auch an viele Dinge sind da schon gedacht worden.
Aber das ist halt einfach, es wird oft riesig.
Was halt mehr kann man damit machen?
Warum?
Ja, da kannst du halt, ja, du kannst da ja ein Format dann definieren.
Du kannst ja halt irgendwie auch definieren, wie die Daten aussehen.
Du kannst beschreiben, wie das, was du da reinschreibst, wann das okay ist.
Du kannst halt eine DTD-Type-Definition zu deinem XML dazu schreiben, das halt sozusagen definiert, wie das Format von deinem XML aussieht.
Und dann kannst du das validieren dagegen und so.
Ja.
Ein heimlicher XML-Fan?
Nein, nein, nein, nein, nein.
Nee, das ist alles sehr schrecklich.
Also, ich meine, man kann das machen, aber das ist alles auch einen Grund, warum das quasi niemand, also niemand tut.
Das ist ja also in der Anfangszeit war das, oder ich, also mittlerweile ist das auch alles nicht mehr so schlimm.
Es gibt gute Bibliotheken, aber es war schon nicht so einfach manchmal.
Und was halt an XML-Nerv-Töten ist, ist halt, du kannst es als Mensch nicht gut lesen.
Es ist halt gigantisch groß.
Hässlich.
Hässlich, ja.
Ja, und dann gibt es natürlich noch sowas wie Yammel oder so, heute irgendwie so ein bisschen auch wieder en vogue.
Auch hässlich.
Das ist auch ein bisschen hässlich, muss man leider sagen, ja.
Wie hat das da jemand voniert?
So irgendwie Yammel, das, was dabei rauskommt, wenn man irgendwie alle Fehler ignoriert, die bei Jason gemacht worden sind.
Und Jason ist das, was rauskommt, wenn man alle Fehler ignoriert, die bei XML gemacht worden sind.
Und die Geschichte wiederholt sich immer und immer wieder.
Irgendwie das nächste Format heißt, was wir nicht gebrauchen.
Genau, das ist halt echt so ein, aber XML ist auch so ein bisschen, das wurde da früher immer gespottet, dass man eben ein Format ansieht, dass es irgendwie von Juristen und nicht von Informatikern konzipiert wurde und dass man irgendwie solche Sachen nicht hat wie, also du kannst es nicht ordentlich quoten.
Wenn du jetzt zum Beispiel, du kannst halt innerhalb von XML, gibt es halt sowas wie Kommentare.
Wie willst du XML-Kommentare quoten?
Das geht überhaupt gar nicht.
Und das heißt, wenn du jetzt zum Beispiel in XML, in einem XML-Dokument beschreiben willst, wie denn jetzt XML auszusehen hat mit XML-Kommentaren, dann passieren ganz schreckliche Sachen.
Das geht alles überhaupt gar nicht.
Und es ist halt so, es kann doch nicht sein, dass daran keiner gedacht hat, dass das jetzt nicht geht.
Das geht einfach nicht.
Und ja, es ist alles, es ist nicht so, es ist nicht so, dass man sich sagt, das ist voll super elegant, total gut, nehmen wir jetzt sofort.
Sondern es ist mehr so, oh, schrecklich.
Und JSON ist aus dieser Perspektive für mich weniger schrecklich.
Also es ist halt, es kann deutlich weniger.
Aber okay, dafür ist es halt alles nicht so schlimm.
Ist ja zum Serialisieren da, also dass man Daten irgendwo hinlegt als Pfeil oder sowas.
Aber es gibt natürlich dann gewisse Begrenzungen, so was halt dann nicht gut funktioniert.
Eben, ja, Datum oder alles, was irgendwie kompliziertere Objekte sind und Code, kannst du aber auch nicht mit reinpacken.
Das geht alles nicht.
Und auch dann für die Übertragung im Netz ist halt auch teilweise nicht so gut, weil das halt dann Text ist und das halt also bestimmte schlechte Eigenschaften.
Du möchtest eigentlich, naja, da gibt es dann sowas, da gibt es ein etwas besseres Format, Message Pack nennt sich das.
Das kann man halt so ähnlich wie JSON bloß.
Binär so, dass das halt irgendwie nicht kaputt gehen kann bei der Übertragung oder nicht so leicht kaputt gehen kann wie JSON.
Ja, und naja.
Aber JSON ist eigentlich schon, würde ich sagen, für viele Fälle so das, was man eigentlich haben will.
Und wenn es dann noch viel komplizierter wird, kann man auch sowas nehmen wie Pickle, da muss man aufpassen.
Ja, es gibt noch in Python selber, wenn ich jetzt überlege, gibt es noch eingebaute Geschichten, es gibt noch Marshall, das Modul, das macht sowas ähnliches wie JSON, bloß halt binär.
Ist auch noch ein Stückchen schneller.
Und dann gibt es noch Shelf, glaube ich.
Das weiß ich aber nicht, aber das habe ich schon ganz lange nicht mehr verwendet.
Und eben, wenn man jetzt aber nicht nur Daten serialisieren will, sondern vielleicht auch Code mit, also komplette Objekte mit Funktionalität, dann ja sowas wie Pickel.
Und Pickel kann man auch schicken als Binärpfeil, dann einfach über das Netz und dann kommt das.
Genau, man kann das in, man verwandelt halt ein komplettes Objekt zum Beispiel in einen binären String und dann schickt man den irgendwie übers Netz.
Auf der anderen Seite deserialisiert man den und dann hat man dieses Objekt wieder da.
Das ist natürlich sehr praktisch.
Was ein bisschen schlecht dran ist, ist halt, man muss halt sehr aufpassen, dass man dann führt der Code aus.
Also wenn einem jemand irgendwie, der nicht vertrauenswürdig ist, irgendwie irgendwas Gepickeltes schickt, da kann ein beliebiger Code drin sein.
Also wenn man das anpickelt, dann führt man das aus, was da drin steht.
Oh oh.
Das heißt, ja, das sollte sich, sollte man sich klar machen, dass das.
Sie hat eine Bombe.
Genau.
Dass man also irgendwas anpickeln, was einem jemand gibt, ist so wie irgendwie Code ausführen, der einem jemand gibt.
Also das ist halt.
Da kann auch eine Briefbombe drin sein.
Man weiß es nie so genau.
Das ist immer auch beim Essen, wenn man isst, was man nicht kennt, dann immer Vorkosta dann niemand.
Ja.
Man weiß nie so genau.
Die Paranoia kann ja beliebig weit getrieben werden.
Genau, genau, genau.
Pickel, lass mal überlegen, es gibt da noch diverse, es gibt da noch für den wissenschaftlichen Bereich ein paar Sachen, es gibt noch HDF5, Net, äh, wie heißt das Ding?
Net CD, ich habe es jetzt wieder vergessen.
Wie der Standard ist.
Es gibt so eben für wissenschaftliche Daten, gibt es noch Standards, wie man, wie man Sachen speichert, die noch so ein bisschen anders sind.
Net CDF, glaube ich, hast du.
HDF5 ist einer der, es gehört da irgendwie mit rein in diese Reihenfolge.
Ja, das hört
sich irgendwie total.
Egal, ja.
Und NumPy-Arrays haben auch nochmal eine eigene Möglichkeit, wie man sie serialisieren kann.
Man kann die auch Memory mappen.
Ja, oder ich meine, CSV ist auch eine Möglichkeit, Sachen zu serialisieren.
CSV ist auch wieder so ein Format, so eigene furchte, fürchterliche, schreckliche Sachen mit sich bringen.
Aber also aus anderer Sicht ist es auch wieder ganz gut.
Also oft würde ich sagen, wenn man die Wahl hat zwischen CSV und XML, ist CSV die bessere Wahl.
Aber ja.
Tja, ja, aber das war es im Grunde eigentlich.
Haben wir noch eine wichtige Serialisierungsgeschichte?
Ja, ich glaube, also wir wollen ja auch eigentlich wollen ja nur eine Minute reden, ich glaube, dann halt mehr
ganz zwei.
Ja, ich habe jetzt noch so ein paar Themen, die sind irgendwie jetzt alle aber sehr unzusammenhängend auch.
Ich überlege gerade, wo ich damit jetzt noch anfangen soll.
Ich glaube, am Memory Management hatten wir schon mal gesprochen.
Ich glaube, in einer der ersten Folgen haben wir über den JIT und den
Gil gesprochen,
den Justin Time Compiler und dann die Global Interpreter Log.
Dann habe ich jetzt noch stehen das Konzept von MapReduce, aber ich weiß ja nicht, was jetzt hier zugehört, dass das irgendwie nicht ganz.
Nee, ich glaube auch, das ist auch so ein bisschen veraltet.
Also das inzwischen macht das keiner mehr.
Und dann, was mich aber natürlich noch interessiert, wenn man halt debuggen möchte, was da irgendwie der Zeug ist, dann gibt es irgendwie so ein bisschen, ich nenne es jetzt mal Deep Debugging.
Das heißt, man kann Deer auf irgendwelche Fehler spawnen oder Help aufrufen und so.
Was gibt es denn da noch?
Und wie würde man sich dann angucken, was überhaupt möglich ist mit so Objekten, die man da zurückbekommt, wo man nicht genau weiß, woran liegt denn das jetzt, guckt man denn da genauer rein?
Naja, ich glaube, das ist schon, also Help zeigt halt den.
Also was macht man Help?
Das ist eine Funktion, die man außen rumschmeißt, um was was zurückkommt, oder?
Ja, aber das, äh, also an den Objekten hängen halt auch immer Dinge dran.
Also zum Beispiel, man an dem Funktionsobjekt hängt da halt auch immer die Dokumente, also der Doc-String hängt da halt mit dran, den man sich dann angucken kann.
Und ich weiß nicht genau, was Help macht, aber Help, glaube ich, wird sowas tun wie die Doc-Strings nehmen und anzeigen, mehr oder weniger.
Und dir zeigt halt alle Attribute und Methoden oder so an an einem Objekt, die da so dranhängen.
Und dann, ja, also zumindest kann man sich dann, zeigt es auch die Funktion Signaturen, glaube ich, an noch.
Was gibt es denn noch?
Nee, mehr verwende ich eigentlich auch praktisch nicht.
Die ist MRO, ne?
Dieses Basis, also wenn man so eine von diesen Objekten, die man mit dir dann rausbekommt, hat sich anguckt, dann bekommt man natürlich noch viel mehr Informationen, weil diese ganzen Magic Methods und Meta-Attribute irgendwie von den Klassen dranhängen, dass man zum Beispiel jetzt mit Basis sehen kann, welche Oberklassen hat denn überhaupt das Ding, wo ich dann drin bin.
Ah, okay, cool.
Habe ich noch nicht verwendet, glaube ich.
Da kann man halt
also ein bisschen tiefer reingucken in dieses Vererbungshierarchie-Ding.
Und dieses MRO, also diese Method Resolution Order, zeigt einem dann vielleicht genau, welches von den Dingen
aufgerufen worden ist, von den
Methoden, die man jetzt in reihenweise überschrieben hat und was da eigentlich hintersteckt, damit man vielleicht weiß, oh, es wurde erst was Falsches aufgerufen.
Also so kann man so ein bisschen immer gucken, wenn irgendwas schief geht, wo man überhaupt nicht weiß, was man da gemacht hat, dass man nicht mehr irgendein Komma gegessen hat.
Ja.
Wie man dann da reinkommt.
Wobei da dann vielleicht auch eine bessere Wahl wäre, einfach direkt einen T-Bugger zu verwenden.
Ja, welchen würdest du
da empfehlen?
Ja, PDB ist halt so das, was und man kann ja auch inzwischen.
Was macht PDB?
Also der stoppt den Code bei zur Ausführzeit, man hat eine Shell und
man an der Hand.
Du kannst halt auch irgendwie zum im Code halt rein Set Trace oder Trace, vielleicht muss ich ja nachgucken, schreibst du halt einfach deinen Code rein und dann hast du da halt einen, stoppt halt die Ausführungen an der Stelle und du hast halt, du kriegst halt ein interaktives Prompt, an dem du halt gucken kannst, was steht denn zum Beispiel in den Variablen drin.
Und dann kannst du halt auch sagen, okay, ich gehe jetzt hier weiter oder ich überspringe das und guck dann wieder, was ist denn da los?
Und genau.
Also und dann weißt du ja genau, wo du bist.
Also das ist eine schöne Geschichte.
Ich weiß jetzt nicht, wann das eingebaut ist, seit wann das Tracing eingebaut ist.
Du bist jetzt auch irgendwann, ist noch nicht so lange her, glaube ich.
Ja, aber Debugger hilft einem da schon deutlich.
Funktioniert halt auch in Django oder so.
Kriegt man das über die Webseite halt dann entsprechende Shell.
Ich glaube, das geht auch hinterher und wie es Code hatte.
Der Editor, der hat das irgendwie auch implementiert.
Ja, das muss ich mir auch nochmal angucken.
Gar nicht richtig benutzt.
Man kann halt dann so Debug-Stops setzen und so.
Ja, ja, Breakpoints.
Introspection, ja genau.
Ja, ich habe jetzt noch zwei andere Widerpunkte drauf, die nichts mehr zu tun.
Zwar einmal, wie löst man Multithreading in Python?
Ja, das funktioniert so wie sonst auch.
Also tatsächlich sind auch Threads in Python tatsächlich ganz normale, bilden sich ab auf Threads im Betriebssystem.
Es ist halt nur so, dass die nicht wirklich parallel Dinge tun können.
Auf unterschiedlichen CPUs sozusagen.
Sie können schon parallel Sachen machen, aber halt natürlich dann nicht so wirklich, wirklich, weil nicht gleichzeitig, weil Sachen auf einer CPU natürlich doch dann irgendwie immer sequentiell abgearbeitet werden, aber ja, das man benutzt sie aber, also daher kann man sie nicht dafür verwenden, um Berechnungen zu parallelisieren, weil eben dafür müsste man es ja auf Prozessoren aufteilen können.
Das geht nicht.
Aber um I.O.
zu multiplexen, geht das ja, geht das ganz hervorragend und das funktioniert gut.
Kann man dafür benutzen.
Ist jetzt nicht so die moderne Art, das zu tun.
Da würde man wahrscheinlich eher sowas wie Async.io nehmen oder so.
Aber man kann auch Threads benutzen.
Das ist völlig okay.
Also Async.io macht dann echt das Multiswelling auf Multiprozessor.
Nee, das macht keinen Swelling.
Async IO ist wieder eine andere Geschichte.
Was ist das?
Async.io ist ja, kann man sagen, einmal eine Event-Loop, sozusagen so ähnlich wie in Node.js oder so auch, wo halt immer geguckt wird, was gibt es denn jetzt gerade zu tun oder so, und dann macht man halt an einer bestimmten Stelle weiter.
Aber vor allen Dingen halt auch eine Syntax, wie man das so hinschreibt, dass das automatisch gehandelt werden kann.
Also ich kann halt sozusagen in Python Funktionen als Async deklarieren und dann kann ich halt die Ausführungen, wenn die zum Beispiel blockieren, halt unterbrechen.
Die werden dann später weiter ausgeführt, wenn es halt wieder was zu tun gibt.
Und ja, das ja, aber das müssten wir ja, wenn man das wirklich erklären will, wie das funktioniert, muss man nochmal eine Folge zu machen.
Das eben, damit kann man halt auch I.O.
multiplexen und das Ganze in einer etwas intuitiveren Art hinschreiben, als wenn man das jetzt mit Threading machen will.
Weil wenn man das mit Threading, mit dem Threading-Modul macht, dann wird es sehr schnell auch sehr unintuitiv.
Und was man auch irgendwie dabei beachten muss, ist halt, wenn man, wenn man, äh, also wenn da Tracepacks kriegt, irgendwo in Wörkern, die halt in unterschiedenen Threads laufen, das kann sehr halt.
Also man, ich meine, das ist halt sowieso das Problem, wenn man jetzt irgendwie Dinge asynchron tut oder so, die halt so irgendwie, man hat nicht mehr so wirklich einen linearen, der Code läuft nicht mehr so linear durch, sondern man weiß halt nie so genau, wo man gerade ist und was da gerade passiert.
Und wenn man da Tracebacks kriegt und viele Threads verwendet und da, dann weiß man manchmal echt gar nicht, was da gerade passiert ist.
Manchmal kommt man in Zuständen raus, die sehr eigenartig sind und das dann immer sehr hässlich zu debuggen.
Also das ist, und das geht mit Async.io deutlich besser.
Also es ist halt deutlich eher so, dass man Code so hinschreibt, als wäre er synchron quasi, aber er dann halt automatisch mehr oder weniger Asynchron, also so ist das halt an den Stellen, wo man auf einen Sys-Call wartet oder so, wo es blockiert, da macht man dann halt an einer anderen Stelle, wo man halt weitermachen kann, weiter.
Und erst dann, wenn dann irgendein Lese, irgendein Read von irgendwie Netzwerkgeschichte zurückkommt, dann geht es halt dann da wieder weiter.
Und ja, also insofern würde ich sagen, also wenn man jetzt erst damit anfängt, dann ist also in IO wahrscheinlich die interessantere Geschichte, die man sich angucken sollte, weil es mehr aussieht wie ein normales Programm.
Aber Sweading kann man durchaus auch machen.
Und es ist wahrscheinlich sogar ein bisschen schneller, wenn man wenig Sweats hat und aber sage ich auch vorschlag, das spielt alles keine große Rolle.
Okay.
Ja, dann was ist Coverage?
Ganz andersiv.
Ja, meinst du das Paket
oder das Modul?
Achso, die Coverage.
Ja, sozusagen wie viel damit gibt man sozusagen an, wie viel Prozent des Codes durchlaufen wird, den man geschrieben hat, wenn man die Tests.
Also man kann ja halt gucken, auch, das geht natürlich ganz gut.
Es gibt auch ein Modul Coverage PY, das das macht, das halt guckt, wie viele von den Zeilen wurden denn aufgerufen, wenn ich jetzt die Tests durchlaufen lasse von meinem Gesamtding.
Und dass dann halt sozusagen die Coverage ist halt sozusagen die Prozentzahl.
Und wenn ich halt 70% habe, dann ist es halt besser, als wenn ich 50% habe.
Wie viel sollte man denn davon haben?
Es gibt Leute, die sagen, man sollte 100% haben.
150.
Weiß ich nicht so genau, ob das ein sinnvolles Ziel ist, weil es für dann manche Sachen sind einfach schwer zu testen und irgendwann wird es halt dann sehr aufwendig.
Und also die ersten 80% sind es ja, wie das so immer ist, gehen relativ einfach und dann die letzten 20% brauchen dann nochmal 80% der Zeit, weil das halt alles so fiese Fälle sind, die man nicht gut testen kann.
Und dann ist halt die Frage, ist es noch sinnvoll, da so viel Zeit reinzustecken, weil den größten Nutzen hat man dann vielleicht schon gehabt, irgendwie in dem Code, der halt einfach zu testen war.
Aber auch da kann man das natürlich vereinfachen, indem man Code so schreibt, dass man ihn einfach testen kann.
Also manchmal mache ich Funktionen, schreibe ich Funktionen nur deswegen, um diese Funktion einzeln testen zu können.
Und ja, oder manchmal macht es Sinn, Dinge auf eine bestimmte Art zu strukturieren, sodass man sie halt leichter testen kann, als wenn man jetzt irgendwie alles in einer Funktion hat oder so, dann ist es halt einfach schwer, die zu testen.
Ja, und möglichst hohe Coverage ist natürlich gut.
Also ich bin jetzt nicht so, ich will jetzt nicht sagen, dass 100% unbedingt notwendig ist, aber viel wäre schon gut.
Und dann gibt es natürlich nochmal auch feine Unterschiede, ob man jetzt nur irgendwie durch den Code durchgelaufen ist.
Hat man aber auch wirklich alle, gibt es für jede unterschiedliche, also wenn man, wenn man sowas wie Condition, so if-else-Geschichten hat, werden auch wirklich, hat man sichergestellt, dass man alle Branches, die dann passieren können, durchlaufen hat und so.
Insofern ist nebenher nicht so ganz klar, was gemeint ist, wenn man jetzt Coverage sagt.
Und ja, das kann man dann auch nochmal, also die, ich glaube, die ursprüngliche Geschichte ist nur so, es ist egal, es müssen nicht alle Branches durchlaufen werden.
Und das will man vielleicht auch anders haben.
Also ich glaube, das kann auch bei Coverage noch einstellen, etwas feiner.
Aber ja, genau.
Das Test Coverage ist halt sozusagen ein Maß dafür, wie viel von dem Code, der in einer Bibliothek ist oder so, wie viel davon ist eigentlich durch Tests überprüft oder ist überhaupt mal ausgeführt worden bei einem Test.
Ja, dann haben wir fast ja schon die letzte Frage, ich glaube, wir sind da schon ziemlich lange wieder heute dabei.
Und zwar auch wieder eine Hörerfrage.
Wie man die Performance, die Speichernutzung der Codes prüfen und vergleichen kann.
Ja, also was ich oft mache, ist tatsächlich, aber das, ich meine, ist halt die Frage, wann das Sinn macht.
Das macht eigentlich erst dann Sinn, wenn man viel Hauptspeicher verbraucht.
Und ich mache das tatsächlich oft so, dass ich einfach mir die Ausgabe von Top angucke.
Und dann sehe ich schon.
Es gibt eine Systemausgabe, wie viel Speicher noch frei ist.
Ja, und wie viel Speicher verbraucht im Prozess.
Und wenn dann halt irgendwas läuft, was ich, dann weiß ich ungefähr, wie viel Speicher das verbrauchen sollte.
Und wenn das doppelt oder dreimal so viel verbraucht, dann weiß ich, dass ich ein Problem habe und vielleicht nochmal irgendwas machen muss.
Es gibt aber auch systematische Ansätze.
Also es gibt zum Beispiel auch eingebauten Profiler in Python, C-Profile heißt, glaube ich, das Modul.
Das kann aber mit Memory-Geschichten nicht so viel machen.
Für Memory-Sachen, glaube ich, da nimmt man dann eher so ein bisschen K-Cache-Grind oder sowas, aber das ist, ich habe das.
Aber wenn man das jetzt im Jupyter Notebook machen möchte, weil man jetzt keinen Pop-Hut oder sowas und.
Du kannst sie halt von den Datenstrukturen anzeigen lassen, wie viel Speicher sie verbrauchen.
Habe ich jetzt auch wieder vergessen, das wusste ich.
Also du kannst in einem Partners Data Frame sagen, irgendwie Mem-Info oder Info oder sowas und dann Deep gleich True oder sowas.
Dann geht das halt, macht das rekursiv, geht das durch diesen Data Frame durch und guckt halt, wie viele Hauptspeicher brauchen da all die Dinge, die da drin sind und sagt dir halt am Ende eine Zahl.
Und dann weißt du halt, okay, in diesem Ding stecken jetzt steckt so viele Speicher drin.
Dein ganzes Jupyter Notebook, also so kannst du deine einzelnen Datenstrukturen angucken.
Bei NumPy-Arrays ist es halt viel einfacher noch.
Ich glaube, da gibt es auch eine Funktion, die einem sagt, wie viel Hauptspeicher irgendwie in Array verwendet, aber da ist es ja einfach, du kannst dir den D-Type angucken von dem Ding und du kannst ja auch angucken mit Shape, wie viel da drin liegt und dann multiplizierst du das einfach mit wie viel Bit hat halt irgendwie der Typ, den ich da verwende, mal Anzahl Einträgen, dann weißt du, wie groß es ist, weil da ist es halt sehr einfach.
Also so kann man bei einzelnen Sachen rausfinden, wie viel Hauptspeicher die verbrauchen, weil wie viel das ein Jupyter Notebook insgesamt verbraucht, siehst du halt im Top.
Speed.
Ja, da brauchst du wahrscheinlich auch einen, brauchst du halt natürlich auch global das bestimmen, indem du halt, also ich auf der Shell schreibe ich auf Time einfach davor und dann kriege ich halt dann eine Ausgabe, wie viel es gedauert hat.
Bei Jupyter-Notebook-Zellen, das gibt es auch halt irgendwie so ein Prozent-Time-Magie.
Du kannst aber, wenn du jetzt einen Benchmark machen möchtest, dafür ist das natürlich nicht gut, das einmal auszuführen oder zweimal, sondern dann möchte man das halt ein paar Mal ausführen, sodass halt dann auch so Cash-Effekte und so nicht so eine Rolle spielen.
Und da gibt es dann halt auch Prozent-Time-It Magie, wo das dann halt 10.000 Mal ausgeführt wird und dann wird dann halt Durchschnitt berechnet und dann ist es so, okay, diese Funktion dauert irgendwie üblicherweise 1,7 Nanosekunden, äh, Millisekunden, Nanosekunden mehr schnell für eine Funktion.
Und da weiß man halt, okay, wenn ich die jetzt und so oft aufrufe, dann dauert das halt.
Ja.
Okay.
Genau.
Und ansonsten eben, C-Profile kann man verwenden, wenn man es genau möchte, wenn man jetzt noch gar keine Ahnung hat, wie man nachgucken möchte und dann rauskriegen möchte, welche Funktion wird eigentlich am häufigsten aufgerufen und wie lange verbringt mein System sozusagen in welchen Funktionen, dann ist es halt so ein Profile eine ganz hilfreiche Geschichte.
Und dann, wenn man weiß, wo man Zeit verbringt, dann kann man halt mit Time It zum Beispiel in einer Notebook-Zelle halt dann irgendwie gucken, ob man das irgendwie optimiert kriegt.
Und dann kann man so die heißen Funktionen ein bisschen optimieren und dann sollte das schneller werden, ja.
Ja.
Ja, das war die letzte Frage, glaube ich, für heute.
Ich glaube, wir sind
tatsächlich irgendwie durch.
Wir haben viel geredet über Python selbst irgendwie.
Ich hoffe, das fandet ihr wieder interessant.
Genau.
Ja, so haben wir noch irgendwie Picks oder sowas?
Pick der Woche.
Ja.
Des Monats.
Ja.
Also ich hätte da noch was.
Ja, was ist dein Pick der Monat?
Und zwar, ich habe mich letztens wieder damit beschäftigt, einen Rechner neu aufzusetzen.
Und hab dann nochmal so irgendwie angeguckt, ob es nicht, wie macht man das eigentlich, vernünftige Python-Entwicklungsumgebungen aufsetzen hat.
So gab es einen Artikel von Jacob Kaplan Moss, glaube ich, der, einer der der Django-Begründer da, hat dazu irgendwie meine Python-Entwicklungsumgebung 2020 Edition oder so einen Artikel geschrieben.
Sollte ich mal verlinken.
Und da dachte ich so, ah, gut, dann guck ich doch mal, was der so macht und dann hören wir mal auf, wie ich das so mache und ob es da irgendwie.
Und das, worauf ich da, eine Geschichte, auf die ich da gestoßen bin, die ich vorher nicht so verwendet habe, weiß gar nicht genau warum.
Ich habe schon davon gehört, haben mir Leute davon erzählt, aber hab's irgendwie nicht benutzt, ist Py-Ent.
Und das war so eine der Geschichten, die ich, äh, also genau, das wäre halt so ein Tick, PyEnt.
Und das war eigentlich ziemlich cool, weil das ist halt ein kleines Tool, was einem dabei hilft, halt Python zu installieren, was überraschend schwer ist.
Das sollte eigentlich nicht so schwer sein, aber es ist halt ganz schön ätzend.
Vor allen Dingen braucht man Python oft in sehr unterschiedlichen Versionen, unterschiedlichen Arten, wie man es installiert.
Für manche Projekte brauche ich halt Minikonder oder Conda und benutze auch Konda zum Installieren von irgendwelchen Abhängigkeiten und so und Paketen in anderen Webentwicklungsgeschichten wieder VirtualEnvs und da eher auch wieder einen anderen Python-Interpreter, jetzt möglicherweise halt einfach einen, der über Homebrew gekommen ist oder den ich einfach so installiert habe oder sowas.
Ja, und ja, also das war immer so ein bisschen doof und mit PyEnv ist das eigentlich relativ einfach.
Da sagt man dann halt, okay, ich hätte gern, äh, also der installiert dann halt auch, PyEnv installiert halt auch Minikonder und sowas.
Und dann kann man halt sagen, okay, PyEnv install Minikonder latest und dann hat man halt die, äh, muss man nicht mehr sich damit beschäftigen, da irgendwie dieses Shell-Skript, äh, also irgendwie Curl in irgendwie Shell-Skript zu Python und dann einen Minikonder zu installieren, sondern das macht, passiert alles für einen automatisch.
Und man kann halt auch pro Verzeichnis dann definieren, was denn jetzt der Interpreter ist, der ausgeführt werden soll, wenn man jetzt da Python eingibt.
Also gibt es dann so einen Punkt Python-Version-File und da steht das dann halt einfach drin.
Und das kann halt unter einem Name von einem Virtual Env sein.
Dann ist man halt in diesem Virtual Env.
Oder es kann halt der Name sein von einem Condor-Environment.
Und das ist halt, das ist halt sehr, sehr cool.
Das heißt, ich hatte vorher so ein Zimmer-MK, also Virtual Enfrapper verwendet und dann immer so mit Post-Activate-Skripten einmal dann halt also ne, ich überlege gerade, ob das nicht ein anderes Thema ist, aber nee, ins Verzeichnis gewechselt und noch so Dinge gemacht und so und das geht eigentlich quasi mittlerweile alles relativ automatisch und man muss halt auch nicht mehr work-on irgendwas sagen, sondern man geht einfach in das Verzeichnis und dann
ist dann ist gut.
Also es funktioniert noch nicht alles hundertprozentig.
Das ist auch noch so eine Idee.
Ich glaube, ich packe das irgendwo, packe ich mir das am besten hin.
Ich habe mir das mal versucht, irgendwann aufzuschreiben, sozusagen, was ich da alles tue.
Und was man so an hilfreichen Tools da verwenden kann.
Vielleicht packe ich das irgendwo auf GitHub in GIST oder so.
Vielleicht haben andere Leute da auch noch Ideen, was man da an tollen Dingen machen kann.
Und vor allen Dingen manche Sachen funktionieren auch nicht so ganz sauber.
Also von irgendwie Virtual End von Nachkonda wechseln, das geht irgendwie aber umgekehrt, das geht irgendwie nicht oder so.
Ist nicht genau warum.
Ja, und vielleicht wäre das immer eine sinnvolle Geschichte, das immer zusammenzutragen.
Was muss man eigentlich machen, um halt eine ordentliche Partnerentwicklungsumgebung irgendwie aufzusetzen?
Auf jeden Fall.
Genau.
Und genau, fand ich jetzt sehr, sehr überzeugend eigentlich und dafür bin ich eigentlich dachte ich mir, warum finde ich das jetzt eigentlich schon immer sozusagen?
Weil das ist einfach so eine Menge Sachen deutlich.
Ja, ich habe auch einen kleinen Blick der Woche.
Ich nehme diesmal Turtle, diese kleine Bibliothek, mit der man kleine Sachen zeichnen kann auf einer Kenner.
Ja, weil da kann man tatsächlich ganz lustige Sachen machen, zum Beispiel Kunst.
Man kann sich Algorithmen, die Mangelbrotmengen berechnen aus Funktionen und der zeichnet dann ganz tolle witzige Bilder, mit denen man Computerkunst macht.
Also unabhängig davon, dass man jetzt eine kleine Schildkröte über den Bild bewegen kann, um einfache grafische Spielchen zu bauen.
Das fand ich sehr witzig, deswegen wollte ich das nochmal picken.
Ja, cool, cool, cool.
Ja, vielen Dank fürs Zuhören.
Also egal wann ihr hört, montags, mittags, abends, nachts.
Bleibt uns gewogen, habt viel Spaß und wir hören uns bald wieder.
Ja, bis zum nächsten Mal.
Tschüss, tschüss.
Im Tag, intakt.
So let's king none.
Dimension Licht spielen, spielen in Personen.
I can't be honest.
Zu fahrfoller Drei klang Dimensionen Zatfollen Licht spielen, spielt Impressionen Die Farbvollen Drei klangs Dimensionen Zurktfreie voll Lichtspielen spielen Impressionen Die Farbfollen
Drei klang Dimensionen Lichtspiel spielen Impressionen der Farbvollen Drei klang dieser Dimensionen voll spielen spielen Impressionen Farbfälle Drei klang dieser D
imensionen sind tanktfollen voll.