Transcript: Fragen über Fragen
Full episode transcript. Timestamps refer to the audio playback.
Ja, hallo liebe Hörerinnen und Hörer, willkommen beim Python-Podcast in der 15. Episode.
Hier ist der Dominik, bei mir ist der Jochen, wir sind wieder im Wintergarten.
Hallo, hallo.
Es ist sicher, diesmal scheint sogar noch die Sonne zu sein, der Wahnsinn.
Ja, es ist auch selten, dass wir aufnehmen, wenn es noch hell ist, aber heute...
Das ist mitten im Winter.
Ja, wir haben tatsächlich Dezember irgendwie...
Ja, der 12. Dezember, genau.
Vielleicht gar nicht so schlecht, wenn wir das mal dazusagen, wenn das ist.
Ja, wir haben uns ein bisschen Zeit gelassen in letzter Zeit, in den Folgen ist mal 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.
Ja, genau.
Das ist immer die Frage, was man da empfindet, wenn man das hört.
Unsere Folge heute soll wirklich mal so eine Anfängerfolge sein.
Ja, wir werden 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, sind ein paar ganz grundlegende Sachen.
Vielleicht wird es ja spannend.
Also, ja.
Keine Leidenschaft.
Die Lava-Folge kennt ihr schon, wen ihr schon gehört habt.
Ja, genau.
Das mit den Themen können wir auch irgendwann mal klassen.
Wir machen einfach mal nur die nächste Lava-Folge.
Ja, ja.
Ja, was machen wir hier eigentlich heute Morgen und was ist so passiert in der Szene?
Und gibt es irgendwas Neues?
Nee, nicht, dass ich, 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 ist natürlich eine tolle Geschichte.
Ich habe das schon gesagt.
Ich habe direkt mal versucht zu installieren und da so ein paar Sachen irgendwie mitzumachen.
Aber habe 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 Faceback kriegt, wenn man versucht,
den Entwicklungsserver zu starten.
Und ja, unter anderem sowas wie Django Model Utils, was irgendwie fast alle Leute verwenden.
Oder ich verwende das eigentlich immer.
Wahrscheinlich auch eine Menge andere Leute.
Wegen Timestamp Model oder sowas, was man ja oft verwendet.
Und ich weiß nicht mehr genau, was es noch alles war.
Es waren, ich habe dann für die Sachen, die nicht funktioniert haben, da habe ich dann
einfach die gefolgt auf GitHub und habe das dann versucht zu fixen und dann halt entsprechend
immer Pull Requests aufgemacht.
Also ihr könntet bei Jochen in den Repos die versuchen, die auch bei Django 3 funktionieren,
wenn das wollen.
Nein, das sollte man vielleicht nicht machen.
Also.
Darum muss ich das irgendwie kennen 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 Projektdings, habe ich
mal versucht, das auf Django 3 umzustellen.
Und das ist mit fünf Einhängigkeiten oder so sind kaputt gegangen.
Und da habe ich, ich glaube, ich habe auch so fünf Pull Requests irgendwie gemacht.
Aber danke, bis irgendwie immer drei.
Oder vier Versionen.
Oder nee, drei.
Also null, eins und zwei.
Und dann ist nämlich ein Major Release.
Was heißt nochmal was?
Ich glaube, null ist immer so die neue Feature Sachen.
Nee, ist immer gerade, ungerade.
Gerade sind immer die Long Term.
Ich glaube, zwei ist Long Term.
Punkt zwei.
Also 2.2, 1.2, 3.2 sind die Long Term.
Und eins.
Ja, kannst du mal nochmal angucken.
Ich bin mir sicher.
Okay, gut.
Sehr gut.
Und eins ist irgendwas anderes.
Das weiß ich nicht.
Aber ja, deswegen habe ich nur gefragt.
Also was man dann macht.
Also für Security Patches dann wahrscheinlich.
Man kann ja nicht mal die 2. 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 hauptruflich
für das Django-Projekt arbeitet,
Carlton Gibson,
dass er empfehlen würde.
Und das machen eigentlich alle Leute,
die da wirklich viel Ahnung von haben,
dass man halt heute, also früher war das wohl mal anders,
aber mittlerweile sind die neuen 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.
Ja, wir haben gerade gesehen, genau.
Also eigentlich, weil das halt macht halt viele andere Sachen
deutlich einfacher, wenn man das so rum macht.
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 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 das,
also bis jetzt auf die 2. 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. Wir können ja runterzählen.
Ja, 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
bei 2 Unicode-Stringen oder so.
So was, 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 auch immer 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 es eine Anfängerfolge
sein sollte.
Und wir fangen schon mit der Ahnung ganz tief in die Materie reinzugehen.
Nee, das ist eigentlich auch nicht so.
Also es sind ein paar,
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
die halt wirklich weg.
Und das heißt, wenn jemand die noch verwendet,
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. Bei Python sag ich schon.
Bei Django 3, 4.
Ja, also diese Geschichte,
diese Geschichten waren jetzt halt dann weg.
Ja, okay.
Und das hat dann auch,
ja, also diverse Pakete gebrochen.
Und insofern, ja, also Umstieg auf Django 3
nicht so super easy.
Wie lange ist jetzt Django 2 rausgekommen?
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.
Ja, also die Release-Zyklen
bei Django sind ja auch viel kürzer geworden.
Also das war
alles viel länger und ja,
Django 2 gab es jetzt gar nicht so lange.
Ja, wenn du noch welche News einst,
weil sonst machen wir tatsächlich weiter mit Content heute.
Ja, Content klingt gut.
Also ich stelle jetzt immer
ein paar blöde Fragen.
Ja.
Und ich versuche dich
dazu zu bringen, dass du die Fragen möglichst kurz beantwortest.
Also so
eine Minute pro Frage oder so.
Vielleicht schaffen wir das.
Wow, okay. Ja, alles klar.
Ich weiß, es wird nicht immer ganz einfach bei einigen Themen.
Es ist natürlich auch was anderes, aber mal gucken.
Ja, schauen wir einfach mal.
Also erste Frage.
Python, eine Schlange.
Ja, wo kommt der Name her?
Also, nee, tatsächlich ist das eine Referenz
auf Monty Python.
Spam, spam, spam, spam, spam, spam.
Genau, genau.
Und auch interessant,
der
Monty Pythons
Flying Circus, also
der Flying Circus ist wiederum
eine Anspielung auf, glaube ich,
Ersten Weltkrieg, Roter Baron
irgendwie, Geschichte.
Die nannte man halt,
das war halt so die
informelle Bezeichnung, weil die halt immer mit Zelten
auf irgendwelchen Äckern und Wiesen
unterwegs waren, weil es sowas wie
Flugflugplätze ja damals noch gar nicht gab,
wurden die dann halt auch mal der
Fliegende Circus genannt.
Ja,
aber wo Monty Python
eigentlich herkommt,
weiß ich jetzt auch nicht.
Genau, aber
die Referenz des Namens
der Programmiersprache bezieht sich schon auf,
äh, Monty Python.
Also ich finde aber eine Schlange eigentlich viel 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
Python-Muster auf meinen Körper tätowieren lasse,
dann ist das natürlich ein Teilchen 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 musst du dich wohl entscheiden.
Ja.
Also, naja.
Ja, die nächste Frage wäre, welche
Einsatzzwecke von Python fallen dir ein?
Hm.
Na ja, schon eine ganze Menge, aber ich würde
sagen, die allerwichtigsten zur Zeit sind
ja, 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
nachschreiben 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
man möchte es tatsächlich einsetzen, dann
kommt man eigentlich um Python nicht wirklich drum herum.
Es sind 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 Scala, also
nicht Java, sondern die Java4M und
meistens verwenden die Leute dann irgendwie Scala
obendrauf und Spark
und da gibt es auch so DataFrames,
aber
ich würde sagen, das ist ein
deutliches Stück kleiner als die Python,
als der PyDataStack.
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,
da wollen wir auch unbedingt noch mal 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, weil so um Weihnachten rum,
dann kann ja auch noch mal 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
ganz viel kleines Zubehör, das irgendwie, wenn ich das richtig
mal verstehe, meistens so in C am besten programmiert ist.
Man hat irgendwie so eine High-Level-API, so wie
MicroPython oder sowas, die man da drauf schmeißt und kann dann einfach
in Python auch die ganzen Module nehmen.
Ja, also die ganzen
Endgeräte,
das ist ja die Frage. Also man kann das, wenn es
so was Arduino-mäßig ist, dann ist das auf C,
was man da normalerweise schreibt, aber
es gibt halt auch mittlerweile Chips,
auf denen man MicroPython
installieren kann und dann kann man da einfach Python schreiben.
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
irgendwie das über Funk, DVB-T
oder so machen, also ein bisschen ätzend
und WLAN ist natürlich schon nicht so schlecht und das geht
eigentlich mit alles mittlerweile, aber halt eben,
ich glaube, der größte Punkt ist, dass 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.
Wir haben ja jetzt nicht irgendeine fertige
Lösung wie jetzt,
na, wie heißt das denn,
von Apple?
Ja, hast du nicht gesehen.
Ja, oder Google
oder Amazon oder so, die haben
natürlich ihre eigenen Geschichten.
Und was ich da interessant, ich habe da
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.
Aber die würden am meisten gerne daran basteln, ne?
Ja, ich war eigentlich,
überrascht, wie viel das ist, weil
das ist ja jetzt eben noch nicht so prominent.
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.
Wir haben doch keine Zeit.
Aber sowas wie Visual Studio zum Beispiel,
VS Code oder so ist in den
Top Ten, TensorFlow und so,
das sind ja alles nur so mehr oder weniger Open Source Projekte,
nicht so richtig eigentlich, aber Home Assistant schon.
Also, ja, da geht auf jeden Fall
auch noch was. Und
ansonsten, ja, alles, was
wir noch so an
Server-Infrastrukturen automatisch hochziehen,
Deployment,
da ist Python auch sehr stark
vertreten.
Das heißt, Web, hat man doch so ganz kurz gesagt,
ist gar nicht so klein, oder?
Nee, Web ist auch sehr groß, ja. Also
Django und Flask sind ungefähr beide gleich
groß, mehr oder weniger.
Und es sind beides große
Bereiche.
Viele der
Top-Seiten sind irgendwie eins von beiden.
Also, genau.
Also,
ziemliche Allround-Sprache eigentlich, kann man sagen.
Ja, okay.
Kann man fast alles mitmachen.
Was sollte man in Python können, um einen Job zu bekommen?
Hmm.
Das, äh,
äh,
hm.
Ich weiß nicht. Also, ich glaube, da kann man,
das ist immer ein bisschen schwer, ne?
Wenn man das dann sagt, was Leute da machen sollen,
und dann sagt irgendwie die Library
oder 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 kann,
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, die man vielleicht lernen kann, ist halt
tatsächlich einfach richtig programmieren können.
Das ist schon so die
Fähigkeit, die man
haben sollte. Oder es ist halt auch etwas, was nicht so...
Es ist ja, äh, 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.
Dann machen Leute irgendwie einen Kurs oder
kaufen sich irgendwie, ich weiß nicht, ob es sowas überhaupt gibt,
Python in 21 Tagen oder Java.
Das geht nicht in 21 Tagen.
Das geht auch nicht in einem halben Jahr. Das dauert alles
ein bisschen länger. Ja, manche Leute denken ja,
dass, wenn sie die Syntax mal einmal gesehen haben...
Genau, dass das das Gleiche wäre. Aber das stimmt halt nicht.
Es ist...
Die Syntax ist ja auch bei Programmiersprachen eigentlich
gar nicht so...
Also, für Anfänger schon. Die verstehen ja erst mal überhaupt nicht,
was da steht. Das ist der erste Schritt zum
Verstehen, was überhaupt, 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,
äh, ja,
es gibt ein paar Verben
sozusagen für Worte. Hast du aber die ganze
Standard-Library mit bedacht?
Klar, also die Libraries sind ja nochmal ein anderes Thema,
aber das muss man ja auch alles gar nicht so unbedingt können.
Ähm, 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.
Und, ja, also, ähm,
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 so eine Geschichte, die dauert
einfach. Äh, da gibt's dann halt auch
Sachen, wie man das schneller hinkriegt und, äh, wie man das
effektiver üben kann und so. Und, ähm,
äh, aber
das, äh, aber wenn man das dann kann, dann
äh, kann man sich
eigentlich in jedes Thema relativ schnell
einarbeiten, würde ich jetzt mal so einfach sagen.
Ja. Und, äh, das ist halt
auch, denke ich, also die entscheidende,
äh, Geschichte, äh, die man, die man
können sollte, ähm.
Solche Themen schnell einarbeiten. Ja,
beziehungsweise halt diese... Die Prinzipien des Programmierens.
Diese, diese Geschichte, die halt lange dauert, halt schon
vorher erledigt haben, weil das, äh,
wird einem niemand gerne bezahlt,
weil, äh, das ist einfach das
lange Dauertum. Aber ich würde auch
sagen, da gibt's halt, äh, ein neues Potenzial.
Jetzt hört sich so ein bisschen an, das kann das ja jeder, aber das ist
nicht so. Also die allermeisten
haben damit Probleme und, und strugglen da
und das, äh, nur ein,
ein, ein, nicht, nicht die Mehrheit aller Programmierer,
äh, haben damit Probleme und, und strugglen da.
Man kann ordentlich programmieren, würde ich jetzt mal so sagen, ne?
Ja, das musst du eigentlich noch definieren, was denn
ordentlich programmieren muss. Und, und, das ist vielleicht auch, das ist auch vielleicht,
ja, das, das kann ich, ehrlich gesagt, gar nicht so genau.
Und, äh, ist auch die Frage, ob, eigentlich
ist es auch wieder so ein bisschen, ne, äh,
ich will eigentlich niemanden ausschließen,
äh, ich,
ich würde sagen, ja, selbst wenn man das nicht so total
hundertprozentig kann, wahrscheinlich haben die
meisten von uns auch schon irgendwie, äh,
Jobs gemacht, wo sie dachten, dass sie dafür, äh,
eigentlich gar nicht geeignet wären oder so und das haben dann halt
irgendwie gelernt, ja. Ich meine, so ist
das halt auch, äh, normal. Das ist wahrscheinlich
auch in anderen Bereichen so und, ähm,
vielleicht muss man sich einfach mal trauen,
irgendwas zu machen oder zu sagen, dass man irgendwas kann,
auch wenn man es halt vielleicht nur so ein bisschen kann und dann nicht so
perfekt, ne, dann, ja.
Ja, aber du musst
ja trotzdem dabei rausfinden, was denn jetzt, äh, richtiges
Programmieren dann überhaupt ist. Also, das ist jetzt zwar eigentlich jetzt nicht
auf meiner Liste, aber da musst du jetzt ein kleines
Kofotos teilen. Ich hab ja sogar zwei Minuten.
Naja,
äh, das wäre gar kein Problem, wenn das in zwei Minuten
zwei Minuten, sag ich mal. Äh, also ich,
ich würde sagen, also wenn man halt
keine, nichts total
äh,
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, nicht nur so ein bisschen
nicht ordentlich sind, sondern
so Kleinigkeiten, sondern dass so Dinge so gar nicht
richtig sind eigentlich. Was, was gehört denn dazu?
Also was würde denn da? Also ich würde, ich würde
sagen, eben das, äh, den, der Umgang mit den,
äh, mit den ganz einfachen
äh, Datenstrukturen,
ja, also irgendwie
Listen, Dicks,
äh, irgendwie
Skalare und damit halt ordentlich umgehen kann.
Also wenn man das schon kann, ist schon viel.
Hat man schon viel. Äh, weil das
schon viele Leute nicht so richtig hinkriegen.
Und, ähm, ja,
dann halt, äh,
dass man eben
Sachen halt ordentlich in Funktionen packt, nicht irgendwie
Spaghetti-Gut schreibt, dass das halt alles so halbwegs, äh,
sondern sich nicht dauernd wiederholt.
Dry, don't criticize yourself.
Ja, und, und
die ganzen, aber da gehen wir fast schon
in diese Detailgeschichten, oder dass man halt,
äh, Tests schreibt und diese ganzen Best Practices,
äh, verwendet und Versionskontrolle
verwendet und so.
Mit den Daten, das muss ich später nochmal sagen, da hab ich noch ein paar Fragen, da, ähm,
müssen wir nochmal ein bisschen drauf eingehen, was denn überhaupt jetzt, ähm,
Skalar, Datenschule, was alles ist, ja.
Ja. 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...
Das Problem ist natürlich, wenn man jetzt jemanden liest, wo du sagst,
dass die Mehrheit der Programmierer ist gar nicht so
hervorragend, und dann lese ich jetzt
von... Oder wie lese ich davon?
Ich würde sagen, da ist viel Verbesserungspotenzial.
Also wenn man sich anguckt, was, was,
wenn der Code, der geschrieben wird von Leuten
oder der so in Firmen, äh, äh, 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 jetzt einen eigenen Code anguckt, dann
ein halbes Jahr später, dann denkt man natürlich schon so, oh, oh, was ist das?
Ja, das ist auch so, ja.
Äh, genau. Aber, äh, ja.
Ja, was,
äh, erstmal, also ich habe noch eine Basisfrage
bekommen vom, vom Olli, der hatte noch geschrieben,
Tipps für eine gute Syntax, also dein Top 5
oder so. Äh, ich,
heute, heutzutage würde ich sagen, Black verwenden
und nicht mehr drüber nachdenken.
Also einfach Black, bumm. Ja.
Vielleicht, also Namen vielleicht auch, äh,
muss man vielleicht... Namen sind natürlich
das sind ganz, ganz, ganz, das ist eine ganz schwierige
Sache, also wie kommt man da auf gute Namen, da muss man
auch lange drüber nachdenken oft, äh,
also, äh, ja, das gibt, da gibt es ja auch
den bekannten Witz, ne, wie, was sind
die zwei schwierigen Sachen?
Äh, ähm, ja, äh,
in der Informatik, äh,
irgendwie Dinge benennen, äh,
Caching und, und oft bei One Error
erhors.
Ja, aber, äh, genau. Also, äh,
Dinge benennen ist, ist, ist schwierig,
ist eine Kunst und, ähm, ja, wo man
sich da auch dran orientieren kann, ist so ein bisschen
wie bei, bei guten Kommentaren.
So sollte eher darauf achten,
hinzuschreiben, warum man das macht oder
was das macht. Nicht so sehr,
wie da irgendwas passiert oder so.
Äh, äh,
ja, und halt dabei,
wenn man verschreibt, äh, äh,
dran denken, dass das, äh,
wenn das, äh, jemand liest,
dann halt verständlich sein sollte, weil Code
viel öfter gelesen wird als geschrieben.
Ja. Okay.
Ähm, was ist mit sowas wie List Comprehension?
Würdest du das bevorzugen gegenüber
klassischen Loops? Nö, kommt, kommt
drauf an. Also, äh, ich würde sogar eher
ein bisschen, die andere, ich würde
sagen, lieber eine, eine, 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, ähm,
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, äh, ich habe dann auch schon
nicht List Comprehensions gebaut, äh, irgendwie,
wo ich dann halt, äh, ähm,
mehrfach verschachtelt irgendwie
über Dinge iteriert habe und das wird bei
List Comprehension sehr, sehr schnell, sehr, sehr
unübersichtlich, ja, wo ich dann halt irgendwie,
äh, stolz darauf war, so ein Statement hingekriegt zu haben,
äh, also, äh, nicht in einer
Zeile, das geht dann halt nicht mehr in einer Zeile,
aber dann so drei Zeilen, List Comprehension
irgendwie, äh, mit Bedingungen
drin und verschachtelt und, äh,
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 draufguckt,
der das, äh,
der das verstehen muss und das unter dem
gewissen Zeitdruck tut, dann, äh,
würde der sich wahrscheinlich irgendwie, äh,
rot vor Hut,
Spaß zur Ärger, da würde sich das,
äh, da gibt's, äh, das Remote
Strangulation-Protokoll irgendwie
zu Hilfe wünschen. Das Remote?
Ja.
Ähm, ich weiß nicht, ähm,
äh, äh,
ja, das kennt wahrscheinlich auch keiner, äh, damals
gab's so ein Text, äh, auch schon lange
her, äh, Bastard Operator from Hell
und, äh,
da gibt's die SysAdmin, äh,
also es gibt die SysAdmin-Man-Pages oder die, äh,
äh, äh, Sys, äh,
äh, Admin Recovery gab's in den News,
äh, News Group
und dann, äh, ASR, ne?
Alt SysAdmin Recovery, das war
die News Group und dann gab's die ASR-Man-Pages
und Tools, äh, ich glaub, wenn man
Man-ASR sagt
oder Man-Knife oder Man-
Snip oder so, dann kriegt man das
auch noch, äh, irgendwie auf dem Linux,
äh, zu sehen, da gibt's dann Tools, mit
denen man, äh, irgendwie Usern,
äh, die, die
Attitüde, äh, Attitüde von, von Usern wieder,
äh, re, re, rejustieren kann
und diese Tools sind halt sowas wie, äh,
Snip
oder Knife ist da, ächs,
ja, so, mit der Axt
irgendwie mal dazwischen geht und, äh, Dinge
gerade richtet und, äh,
Regulieren, das hört sich toll an.
Ja, das klingt, äh, klingt nach Spaß an,
äh, wenn man auf der richtigen Seite steht.
Äh, ja, ist natürlich
so ein bisschen, ich mein, das Mindset dahinter ist
auch etwas fragwürdig, aber es ist damals
was irgendwie lustig und, äh, eines
der, da gab's auch Protokolle und eines der Protokolle
in dem Zusammenhang ist halt, dass, äh,
äh, es, äh, äh,
RSCP, RS, äh,
äh, eben, Remote Strangulation Protokoll
mit einer Software über
Fernverbindungen.
Sehr gut. Ja, also, ne,
das ist das, was man in Startorganisationen
gerne hätte oder wo man dran arbeitet, das auch
zu bekommen, ja. Also ihr braucht gute Admins
für den Start, damit das funktioniert. Ähm,
ja.
Ja, also, okay, ein bisschen Syntax haben wir gemacht, ja,
also die Frage wäre jetzt noch, was gehört als zu
Python Fullstack dann? Also wenn man jetzt schon
ganz viel kann und so, was würdest du sagen, wenn man richtig
Fullstack entwickelt? Ja, Fullstack, ja, das ist so
ein Ding, was heutzutage auch wieder, äh, in aller
Munde ist, wobei das auch selten tatsächlich
so ist.
Würde ich sogar sagen, auch, das ist auch das, ich mach das nicht,
eigentlich, ich bin deutlich eher auf der Backend-Seite
als auf der Frontend-Seite, aber
Fullstack hieße ja, dass du quasi alles
machen kannst, von unten bis, äh,
also Frontend. Also Fullstack in Python geht gar nicht, weil
das geht nicht richtig, genau, weil du mit Frontend
bist du halt nicht, äh, da brauchst du
halt dann schon JavaScript für
und, ähm, ja, oder
es ginge theoretisch auch, aber das ist halt ein
Bereich, der schön wäre, wenn das mit Python funktionieren
würde, aber 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, ähm, eben nicht
so viel wie für JavaScript, die ganzen
UI-Bibliotheken, die man da so braucht, um halt
Dinge irgendwie auszumachen, also
schwierig.
Ja, okay. Ja, das heißt,
JavaScript braucht ihr, wenn ihr Fullstack machen wollt, und wenn du
Python kriegst, dann kannst du hin. Aber ja, vielleicht
wollt ihr das ja auch gar nicht so machen, weil, warum sollte man
Fullstack machen, wenn man sich andere Sachen wie Data und
Backend so gut kennt? 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. Hätte man ein bisschen
CSS-Forschung machen oder sowas, ja.
Ja, okay. Auch kein Python.
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 ja so ein paar Framework, ne?
Grid, Materialize und so.
Naja, also ohne JavaScript.
Aber das ist ja was anderes. Ja,
Fullstack geht gar nicht ohne Python.
Ja, und das ist tatsächlich
auch einer der großen
Risiken irgendwie für die Zukunft von
Python, wenn das halt, wenn das
quasi so aus dem Wettding, 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
was halt, dann schreibst du einmal den Code, kannst den
im Backend und im Frontend verwenden.
Wenn wir jetzt auch
im Backend zunehmend JavaScript kriegen,
dann brauchst du halt eigentlich Python
in der Webentwicklung gar nicht mehr. Oder?
Es läuft umgekehrt. Und
wir kriegen auch irgendwann Python im Frontend.
Das wäre natürlich eigentlich die schönere Variante.
Ja, da müssen wir mal dran arbeiten, dass das passiert.
Ja.
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, Sun of 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.
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. Sun of Python,
also die Prinzipien, die man
sich drauf geeinigt hat, die in Python gelten,
sollen auch sein.
Da ist auch immer so ein bisschen Humor mit dabei.
Aber ja,
ist auch was dran. Ja, also das ist direkt
verknüpft zu PEP 8. Ich glaube, das hatten wir dann auch schon mal kurz
erwähnt, aber an der Stelle vielleicht nochmal.
Einfach nur die Art, wie man
relativ minimalistischer
Konsens
darüber, wie man Python-Code
formatieren sollte, vielleicht.
Und wer macht das nicht, dann
kommt ihr in die Python-Höhe. Ja,
aber auch innerhalb von PEP 8 gibt es ja so
Dinge, die dann nicht geklärt sind dadurch.
Und
Black hat halt zum Beispiel eben eine Meinung
dazu, wie das sein soll.
Das ist bei einigen Sachen total furchtbar. Das sieht
scheußlich 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 da drunter
die Klammer wieder zu, wo ich
dann sagen würde, hey, für die fünf Zeilen,
wenn das Print-Statement eh länger als 89 Zeichen ist,
hättest du das auch einfach in eine Zeile 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 die Klammer 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 diesen 89 Zeichen
Editor-Quatsch, weil ganz ehrlich,
so entziehen, dass wir
nur 89 Zeichen auf dem Bildschirm haben.
79. 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.
Es ist auch so, 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.
Ja, zum Beispiel.
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 an einem 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 über die Konsole.
Hast du dich mal an eine Konsole
gestellt, an einem Rechner zu drum, an eine serielle
Konsole? Ich glaube, da hast du
genau die 80 Spalten
und 24...
Das ist ja uralt, DOS.
Ja, bei DOS war das auch so, genau.
Ja.
Ja.
Ich weiß gar nicht.
Also ich glaube auch nicht, das ist eigentlich nicht mehr relevant, aber
da kommt das halt her und...
Wenn, dann sieht man da halt, muss man kurz darauf aufpassen,
dass es dann umgebrochene Zeilen gibt.
Die automatisch vielleicht eingeguckt werden oder so.
Ich weiß gar nicht, auf was ich es gestellt habe
bei mir. Das ist ja auch ein Ding, das man bei Black
tatsächlich einstellen kann. Also da...
Das muss man nicht so
auf 79 zeichnen lassen.
Also 79 zeichnen deswegen, weil man halt noch eins braucht
von der Zeilung.
Ja. Aber...
Wenn...
Also ich glaube, ich habe es auch nur auf einer 10 stehen.
Ich weiß es nicht.
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.
Irgendwann ist es natürlich auch wieder doof, wenn das halt zu lang wird.
Ja, gut.
Also so, dass man es halt vernünftig auf einem normalen Arbeitsrechner
irgendwie von sich an lesen kann, dass es nicht immer halb so groß ist,
dass man viel zu viel Platz braucht. Das wäre ja völlig unheimlich
und hässlich, einige Sachen.
Also ich finde, Black ist dann so ein bisschen inkonsistent, wenn es halt dann...
Beispielsweise, du hast drei Debug-Statements
hintereinander. Das eine ist vier Zeichen zu lang,
dann bricht der jetzt ganz komisch rum, irgendwie
und die anderen darunter
sehen nicht so aus. Das ist irgendwie
komisch. Naja.
Also ich finde, mein ästhetisches
Empfinden wird da immer so ein bisschen angehört.
Naja, gut.
Wann ist man Amnesie-Syndrom erkrankt?
Ah.
Not invented hier, ja.
Das...
Ja, ja, ja.
Wenn man alles selber 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,
viele Firmen haben das auch, die ja alles
doof finden, was sie nicht selber gemacht haben und dann
halt viel zu viel selber machen. Das ist natürlich ein Problem.
Wir entfinden das Rad nochmal von vorn.
Genau.
Das ist halt immer nett, da kann man immer was damit lernen.
Also die Grundlagen zu verstehen, das kann ich so schlecht.
Und hat man irgendwann nicht, kein mehr, der versteht,
wie es irgendwann mal gebaut worden ist,
so nur noch Leute, die dann irgendwie auf dem Sand
und der Asche von alten versunkenen Städten
versuchen, neue Gebäude zu errichten.
Und dann immer so, oh, da war eine Grube.
Oder ein Schützerpalast 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,
obwohl man eigentlich schon irgendwie fliegen könnte.
Ja, es ist
immer schwierig. Man muss halt eine richtige
Balance finden. Es ist manchmal gut,
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,
da hat es dann auch so,
wie meinte ich, Jango 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.
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 ist ja auch wieder
blöd, wenn man nichts selber macht.
Ganz schlimm, NPM 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.
Ja, Paketversionierung muss immer stimmen und genau
dem Stufstand 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 dir irgendwas auseinander, weil das inkompatibel
ist mit irgendeiner neuen Implementierung.
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,
ja,
irgendwie einen Weg,
finden, der für den Anwendungsfall,
den man hat, den besten Trade-Off bietet.
Aber tatsächlich
ist es so, dass die meisten Leute eher
zu viel Richtung Not-Invented
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 anfängt, 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 waren, 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 abstrakter
Geschichten. Das ist halt auch die Frage, inwiefern das
nicht unter Umständen...
Auf der einen Seite kann man sagen, man kann heute
mit viel weniger Zeilencode
viel kompliziertere Dinge und
tollere Sachen bauen. Auf der anderen Seite ist es halt, wenn man
sich das manchmal genauer anguckt, ist halt
steht das alles so ein bisschen auf
tönernen Füßen. Das ist halt so Kartenhaus über
Kartenhaus-Geschichte.
Auf den unteren Ebenen stimmen schon viele Sachen
nicht mehr so richtig, aber dann baut man halt so lange
Abstraktionen drüber, bis es wieder...
Aber in Wirklichkeit
hat man diese Probleme nicht wirklich gelöst.
Wenn man halt das Gebäude und den Palast auf der Samtgrube baut,
man kann tatsächlich noch ein paar Stahlträger einziehen, das dann zu tun
könnte, der Palast zu gehalten.
Das ist halt dann...
Ja.
Aha. Ja, aber jetzt gehen wir, glaube ich,
jetzt haben wir so ein bisschen generell darüber gesprochen, was
so Python generell
ausmacht. Jetzt gehen wir so ein bisschen tiefer
in die Probleme der...
Oder was heißt die Probleme? Die Ideen, die Konzepte
der eigentlichen Sprache, was man auch vielleicht
achten muss. Also, falls ihr noch Fragen habt, die ich nicht beantwortet hatte,
schreibt uns wieder, wie immer.
Hallo, AppPython Podcast.
Wofür ist die InetPy?
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.
Mhm. Irgendwie so. Und dann kann man da direkt
aktiv drauf zugreifen. Aber die Frage ist halt,
warum man das dann nicht mit den Submodulen macht.
Nee, du kannst das ja auch
reinschreiben,
was du exportieren willst, welche Symbole.
Interessant ist, kann man da auch Sachen ausschließen?
Also, dass ich zum Beispiel sage, ja, aber diesen 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 ein Folder,
importieren. Also, indem man halt
relativ einen Zugriff drauf hat.
Und dann einfach sagen, import
Foldername oder sowas. Und wenn da eine
InitPy drin ist, dann kann man die Module,
die da drin sind, einfach aufrufen.
Mit einem Import-Teil. 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
irgendwie so ein Ding ist. Also, 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ützlich. 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 InitPy
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 da eine InitPy fehlt.
Irgendwann weiß man halt einfach so, ah, das sieht jetzt danach aus.
Okay, das könnte sein, dass da einfach eine InitPy fehlt.
Aber ich habe zehn Minuten da vor meinem
Bildschirm gestanden und überlegt, warum macht der jetzt nicht
die Migration von meinem Dankmodell, den ich da geschrieben
habe? Das verstehe ich nicht. Und dann fehlte
einfach die InitPy Migration-Spoiler und dann, also
ach so, ja klar, kennt der ja nicht, kann der ja gar nicht sehen.
Ja. Aber da muss man auch drauf kommen
tatsächlich, sonst. Ja, das ist 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 noch mal
beschäftigen. Aber da müsste ich mich auch erstmal anlesen.
Weiß ich jetzt alles gar nicht so genau.
Ja, kriegen wir bestimmt noch jeden Tag. Aber wir haben
ja schon die Minute schon wieder überschritten. Ah ja, gut.
Ja, aber InitPy ist halt, wenn man
mit dann, dann, also Doppel-Underscore 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,
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, also angefasst
werden sollten, die werden
halt mit Doppel-Underscore
halt irgendwie gepräfixt
und Sachen, die halt sozusagen
dann gibt es
einfach ein Underscore, das ist halt so
markiert für
ja,
also
kann, ist auch, sollte man
nicht, sollte man nicht, ist auch eher so
interner Gebrauch, ja, aber ist jetzt nicht so total
privat.
Ja,
also ist es eine Konvention,
im Grunde braucht man das auch, also
außer jetzt manchmal bei
bei Doppel-Underscore
eigentlich auch nicht
wirklich, also jedenfalls.
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, sag mal,
im Magic-Method-Kontext von
Klassen, wo man halt dann irgendwelche magischen Methoden,
die es im Identitätsüberschreiben will, um andere Effekte
zu erzeugen, aber...
Ja, es ist halt so ein Hinweis
darauf, dass man da
nicht wirklich
mit interagieren sollte.
Nicht umfummeln, ich fasse meine Klasse nicht an.
Alles, was man selber schreibt, machen immer
anders vor, damit niemand anderes es macht.
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 der Methode, ja, also
ein bestimmtes Attribut ist
eine Property von dieser Klasse,
also hat ein Property-Dekorator drüber, irgendwas wird
ausgerechnet und du schreibst
das Ergebnis dieser Berechnung, also prüfst,
also,
wenn du die Methode aufrufst, zuerst habe ich das schon
ausgerechnet, wenn ja, gibst du
einfach das
gecachete, den gecacheten 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-Attribut
ab. Underscore-Cache. Ja.
Oder Underscore
dieser Name dieses Attributes
oder so, weil,
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 gecacheten 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
sein, dass Dinge schief gehen.
Und das heißt,
ja, das ist halt so eine Markierung für
das Ding hier bitte nicht direkt verwenden,
sondern, ne, dann gibt es ja meistens ein öffentliches
Attribut,
was man benutzen kann und dann
kann die Klasse das intern handeln.
Was ist denn überhaupt eine API?
Ja, im Grunde
eine Schnittstelle, die Schnittstelle
zu irgendwas. Es 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, Party-Django-Paket
oder eine Python-Bibliothek oder so,
dann ist die API das, was man
sozusagen von außen benutzt.
Die besteht ja aus ganz vielen Funktionen.
Die man für seine Bibliothek benutzen kann,
um die Anwendung,
um damit irgendwas zu machen. Also wenn ich jetzt
zum Beispiel jetzt Requests nehme oder so,
dann macht request.get
macht halt ein get-Request. Das ist halt der öffentliche.
Intern macht das dann unter Umständen
noch eine ganze Menge anderer 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, ja, für internen Brauch.
Ja.
Was ist eine private 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 so. Also ich hatte es gerade so in den
Anfängertagen ganz oft so, dass ich irgendwie mir
dachte, so ja, private Variable,
das ist alles irgendwie ein bisschen blöd. Ich muss ja irgendwie von einer Funktion
immer irgendwie so einen Wert returnen und damit das dann,
also ich glaube im Kontext einer Funktion sind ja die
eigentlich die Variablen immer privat.
Nein, nee, das ist nur eine Verwechslung. Also du meinst
lokal, lokal und global.
Privat und öffentlich,
das ist halt genau diese Geschichte mit dem Double-Andersquad.
Ja, okay. Dann meinte ich lokal
und global, ja.
Also lokal heißt, Variablen sind
halt quasi in dem
Block
gültig.
Und global.
Und ich habe immer gehört, man braucht keine globale,
man darf die nicht nehmen und das ist total nicht so
backrested. Kann man schon.
An einigen Stellen habe ich halt gemerkt, also gerade ich habe manchmal so Spiele
rein,
gemacht, Spiele gebaut oder sowas, da haben das
total super geholfen, weil das 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
durchaus
praktische Anwendungsfälle
hat.
Ist jetzt nicht unbedingt immer so guter, also es kommt
halt drauf 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 den 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 in 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 dem
an diesem Ding irgendwie rumgeschraubt wird, auch passiert.
Warum?
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 nennen würde.
Ich habe jetzt ein Spiel, mein Barbar hat
Lebensenergie von 100 und es gibt
bestimmte Funktionen, die aufgerufen werden, wenn
der Barbar irgendwas macht, falsch macht, richtig macht,
runterfällt, gegen einen anderen, gegen einen Monster kämpft,
dann würde ich von dieser
globalen Lebensenergie irgendwas abziehen.
Ja.
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 ja, naja,
lass mal überlegen, kann ich irgendwas konstruieren,
was dann problematisch
wird? Ich meine, es kann ja auch Dinge geben, 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 jetzt,
sonst könntest du dich ja auch wieder
lebendig machen,
sozusagen, wenn du tot bist,
eigentlich. Ein Lifehack, ja.
Du musst irgendwie den,
ja, irgendwas musst du diesen State verwalten.
Irgendwas musst du 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, es ist...
Also, das würde nicht so gut funktionieren.
Das heißt, da würde man auch auch klassenbasiert
einen Ansatz nehmen, wo man irgendwie sowas machen
wie erhöhe Lebenspunkte und reduziere Lebenspunkte
und der macht das halt dann nur dann, wenn man nicht tot ist.
Oder so. Genau, und das erhöhe Lebenspunkte
geht halt nur, solange man nicht tot ist, zum Beispiel.
Aber diese Logik, wie das funktioniert,
wäre dann halt an einem Ort
gebündelt. Das wäre so ein bisschen die Idee auch hinter Klassen.
Haupt hinter
Objekt oder Theaterprogrammierung, dass du halt
die ganze Komplexität irgendwie
verbirgst.
Hinter, ja,
hinter dieser...
In diesem Objekt, hinter einer API.
Genau, und dann das halt alles nicht mehr wissen musst.
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 um jetzt dann doch Sinn?
Ich würde ich...
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-Personen.
Oh, Singleton, das steht hier ein bisschen weiter unten.
Nein, Singleton.
Ja, okay.
Was ist ein Singleton?
Was ist ein Borg-Personen?
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
die Spielfigur
oder so, die dann bestimmte Eigenschaften hat,
wie eben sowas wie Lebensenergie oder so,
wenn ich garantieren möchte,
dass alle, die damit interagieren,
immer die gleiche Instanz haben,
dass ich halt den nicht, weil es gibt nur einen,
es ist ja jetzt blöd, wenn ich zwei davon erzeuge
und dann in dem einen Objekt
verjähre ich die Lebensenergie und beim 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, nee,
eigentlich, also,
dann kommt es in Borg-Python, so wird das üblicherweise
dann in Python implementiert,
man macht es einfach so, dass
wie ging das?
Also, ich glaube, der Trick ist,
aber das muss man mal nachgucken,
also mit Vorsicht genießen,
ist das sozusagen
den State innerhalb
von der,
eines Objekts sozusagen
in der Klassenvariable zu halten, die halt
bei allen Instanzen gleich ist. Und das, dann 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änger-Vorbuch
gibt es halt das Pattern Singleton,
weil man eben nicht
immer tatsächlich, also ich glaube,
bei der ursprünglichen Singleton-Beschreibung,
das wird einfach immer die
gleiche Instanz returnt, wenn man halt die...
Also, das heißt, wenn du überschreiben, das würde halt bedeuten,
wenn es dann ein anderes gibt, returnt es halt das.
Returnt es das alte halt.
Sowas kann man auch in Python machen, das wäre 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,
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, aber genau,
das sind alles, es geht immer so um State Handling
im Grunde, das ist immer so,
und wer manipuliert den und wie kann man
dafür sorgen, dass man
den Code,
der den State manipuliert, an einer Stelle
behält und so.
Weil das ist immer so, das ist was, was man am Anfang
das ist ein bisschen unintuitiv,
das denkt man sich so, naja,
das ist ja kein Problem, State kann irgendwo sein,
egal, ist in einer Variable,
in 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,
und zieht das dann durch, unabhängig
davon, wie das Problem eigentlich ist.
Und das fiese, was
manchmal dann, oder fast immer passiert,
ist, dass man dann halt den State verteilt
über viel Code und
das ist dann halt
das, was du
speichern musst,
was sich irgendwie ändert.
Also,
der Status.
Ja,
also, sagen wir mal so, bei einer Web-Applikation
würde man sagen, dass der State
einer Web-Applikation liegt üblicherweise dann eben
in einer Datenbank.
Also, das ist in der klassischen...
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 das halt nicht dynamisch generiert,
sondern es liegt dann irgendwo rum.
Ja.
Das heißt, wenn man das ändern möchte,
dann muss man erst die Datenbank fragen oder sowas.
Das macht man dann gar nicht woanders.
Ja, genau.
Also,
das, was halt sozusagen
beschreibt, in welchem Zustand
deine Applikation ist.
Gehen wir jetzt nochmal aufs Spiel kurz.
Was mit der Figur ist. Was hat die gerade für eine Waffe in der Hand?
Was für eine Energie hat die? Wie viel Rüstung hat die noch an?
Das wäre der State.
Es geht so 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 eine Adventure ist.
Und ich darf aber auch keine zwei gleichzeitigen Sachen
dann irgendwie haben.
Damit das sich jetzt nicht widerspricht,
darf es immer nur ein State geben.
Die interessante Frage ist,
wie verwaltet man diesen State?
Und naiv wäre halt,
man hat halt zum Beispiel
Held heißt halt in irgendwelchen globalen Variablen.
Man hat halt eine Liste.
Linke Hand, rechte Hand.
Die ist halt global.
Genau, da steht halt drin,
hier ist 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 ist Logik jetzt irgendwie
solche Sachen abbildet,
wie das Flammenschwert macht jetzt plus 10 Angriff,
aber auf der anderen Seite wird dir heiß.
Das heißt, wird dir die Hand heiß
und du verlierst irgendwie alle halbe Stunde
ein paar Lebenspunkte oder sowas.
Keine Ahnung.
Das ist ja 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 ab einer gewissen Größe nicht mehr.
Das geht am Anfang,
geht das,
solange es alles sehr klein ist,
kriegt man das auch noch hin,
dass man das alles im Kopf behält.
Ja, 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 nehmen wir 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,
dass das halt irgendwie tut.
Und dabei bedenkst du aber nicht,
dass unter bestimmten Umständen
irgendwelcher anderer 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 irgendwann
was anderes,
was wiederum nochmal was anderes macht.
Ich bin der Invincible Geist.
Ja.
Ja.
Und das Mittel dagegen ist halt,
dass du eben nicht direkt die Daten
pro 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 dann eine API nach außen,
die öffentlich ist.
Und,
äh,
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.
Ähm,
äh,
ich würde es jetzt mal sagen,
das erklärt aber nicht viel,
äh,
ist halt die Instanz,
äh,
konkretisierte Instanz von irgendwie
einer Klasse.
Also,
in einer Klasse definiert man sozusagen,
irgendwie,
äh,
ja,
äh,
äh,
eben eine Zusammenfassung von,
von,
von irgendwie Code,
der was tut.
Und,
äh,
irgendwie Daten,
äh,
die man irgendwie halten will.
Und,
ähm,
wenn man das jetzt,
das ist halt sozusagen die,
die,
äh,
Beschreibung.
Und wenn man da jetzt rauskommt.
Ich sag nicht so besonders an von dem Code,
der irgendwie,
irgendwie Beschreibung von irgendwelchen Sachen.
Ja,
also,
äh,
man könnte das vielleicht,
also,
äh.
Also ein Objekt ist ein Ding.
Also ich glaube in Python ist alles ein Ding.
Oder ein Objekt,
oder?
Alles ein Objekt,
ja.
Also,
also alles was es in Python gibt,
kann sich als Objekt darstellen.
Also ein Objekt ist immer,
ein Instanz einer Klasse,
wenn man das so sagt.
Ja.
Das heißt,
ähm,
alles was ihr habt in Python sind tatsächlich Instanzen von irgendwelchen Klassen,
von irgendwelchen Dingen.
Ja.
Ähm,
da,
die nächste Frage war,
was ist Self?
Self ist,
äh,
immer das Objekt selbst.
Also wenn man,
wenn das Objekt,
auch eine,
ist eine Konvention sozusagen,
dass man das so nennt.
Aber,
äh,
sehr sinnvoll das so zu machen.
Außer,
es gibt wiederum Spezialfälle,
bei denen man das ein bisschen anders macht.
Also,
wenn man,
ähm,
äh,
äh,
eine Methode hat,
also Methode ist nichts weiter als eine Funktion,
die sozusagen an so ein,
so eine,
Instanz an so ein Objekt gebunden ist.
Und,
ähm,
jetzt möchte man halt,
äh,
um zum Beispiel auf die Daten,
die man halten möchte,
in so einem Objekt,
äh,
äh,
um da drauf zuzugreifen,
muss man ja irgendwie sich selbst referenzieren können.
Deswegen wird immer als erstes Argument in Methoden,
äh,
das ist halt auch das,
was dann Methoden von Funktionen unterscheidet,
äh,
immer,
äh,
eine Referenz auf,
das,
äh,
auf,
auf sich selbst,
äh,
sozusagen mit übergeben.
Ja.
Man könnte das auch anders nennen.
Ja,
man kann auch sagen,
äh,
A statt Self,
dann ist es A,
aber,
ähm,
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 gerade,
was man gerade ist.
Und dann kann man halt auf Self-Punkt irgendwelche Daten zugreifen.
Okay.
Ähm,
da fangen wir jetzt direkt ein paar andere Sachen ein,
weil wir jetzt das gerade jetzt so hatten mit Objekt,
ne,
was ist denn ein Objekt?
Dann ist das eine Klasse.
Und jetzt gibt es irgendwie drei Dekoratoren,
also wir müssen noch gleich darüber sprechen,
was ein Dekorator ist,
aber es gibt drei Dekoratoren,
die,
ähm,
Python verwendet,
die da immer so drüber stehen.
Das ist Dessig-Method,
Class-Method und,
ähm,
Property.
Über Property hattest du eben auch schon.
Ähm,
was ist denn jetzt da irgendwie so der kleine Haken?
Also wann sagt man jetzt zum Beispiel,
das ist eine statische Methode?
Und wann sagt man,
das ist eine Klassenmethode?
Was,
was,
was heißt das denn in dem Kontext?
To Self und Objekt und,
äh,
Ja,
also ich würde,
ich würde eigentlich,
ähm,
am liebsten mit,
äh,
der Klassenmethode anfangen.
Also,
äh,
äh,
Class-Method.
Class-Method ist,
äh,
halt eine,
ähm,
äh,
eine Methode,
die eben nicht eine konkrete Instanz,
äh,
Das heißt,
da fehlt auch Self bei der,
Genau,
da,
da könnte man jetzt auch Self übergeben,
also es wäre dann sehr verwirrend.
Sondern was man da üblicherweise,
äh,
übergibt,
äh,
ist,
äh,
man CLS oder so und bekommt man die Klasse übergeben.
Na,
die Klasse ist auch wieder ein Objekt.
Das ist auch irgendwie,
man kann das auch noch ein Stückchen weiter treiben,
auch dann mit,
mit Metaklassen.
Aber,
Also die kleinste,
das kleinste Objekt,
also jede Klasse ist irgendwie ein Objekt und das Objekt,
Objekt und Objekt selber ist ein Objekt vom Typ,
Typ.
Hm.
Ja,
okay.
Ja,
okay.
Ähm,
man,
äh,
ja,
also,
ähm,
jedenfalls,
wenn,
in der,
in der Klassenmethode übergibt man halt CLS und nicht,
äh,
Self.
Weil man damit,
man halt weiß,
dass man jetzt gerade die Klasse in der Hand hat und nicht,
äh,
nicht,
äh,
eine Referenz auf,
äh,
die Instanz.
Und,
ähm,
äh,
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,
äh,
internen Daten oder so zugreifen,
weil die hat man ja nicht.
Sondern,
die machen halt,
die,
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 verwalten,
verhalten,
verhalten sie in gewisser Weise natürlich dann so wie,
eine normale Funktion.
Ähm,
und vielleicht können sie auch auf Daten,
die halt für alle Instanzen dieser Klasse gleich sind,
zugreifen eben über die Klasse.
Aber,
ähm,
die brauchen jetzt nicht die,
ähm,
nicht,
nicht irgendwie eine konkrete Instanz,
auf der sie irgendwas machen.
Also Beispiel für,
äh,
sowas sind,
was ist denn ein gutes Beispiel für,
äh,
jetzt bin ich schon aus dem Spiel.
Also,
die können zwei Beispiele,
ich kann es,
äh,
gut visualisieren finde.
Entweder hat man so ein Spiel,
mit so Charakteren und so,
oder man hat so ein Universum mit Planeten und Dingen,
die umeinander kreisen oder sowas.
Zwei verschiedene Sonnensysteme als zwei Klasse.
Oh je.
Aber okay,
lass mir das.
Äh,
ich weiß nicht genau,
ob ich was da irgendwie,
also,
äh,
mir fällt da jetzt gar nichts.
Also ich,
man hat,
also es sind oft irgendwelche Hilfsfunktionen oder so,
die,
äh,
was machen,
was logisch dann in der Klasse gehört,
aber wo man nicht mit einer konkreten Instanz irgendwas,
äh,
zu tun hat.
Mir fällt jetzt tatsächlich kein super tolles Beispiel.
Was ist denn der besten Static Method?
Was wäre das denn jetzt so als?
Ja,
Static Method,
ähm,
ah,
die bekommt halt einfach tatsächlich überhaupt nicht mal die Klasse,
ja.
Aber im Prinzip ist es nichts anderes,
außer,
ähm,
sie nur nicht mal die Klasse bekommt.
Ja.
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 Objekts aufrufbar ist,
oder so.
Ja.
Ja,
was ist jetzt in dem Vergleich eine Static Method?
Okay.
Ja,
also,
äh,
Static Method,
äh,
bekommt gar keiner,
äh,
gar kein,
auch ein automatisches,
äh,
Argument mit,
äh,
sozusagen,
also das wäre dann die reine,
äh,
wäre quasi wie eine Funktion,
ja,
also es ist egal,
ob man jetzt Static Method,
äh,
aufruft oder halt,
ähm,
äh,
ähm,
Funktion von draußen,
Funktion von draußen,
genau,
genau.
Ah,
äh,
äh,
richtig,
jetzt fällt mir doch wieder ein Beispiel ein zu Class Method,
wo das,
äh,
äh,
äh,
wenn man jetzt,
äh,
in,
in Django zum Beispiel Modelle hat,
dann,
äh,
sind halt,
ähm,
äh,
viele,
äh,
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,
äh,
die Geschichten stehen halt in der Datenbank,
und jetzt eine konkrete,
konkrete Instanz eines,
also Django Modelle sind Klassen,
äh,
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,
äh,
Beispiel User nehme,
ja,
also ein User Objekt,
äh,
in Django ist halt eine Zeile aus der Tabelle Users irgendwie,
und,
äh,
hat halt all die Attribute,
die jetzt irgendwie die Zeile hat,
also als Spalten hat,
sozusagen in dieser Tabelle,
ja.
Ja,
ähm,
aber jetzt,
äh,
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,
äh,
sag ich dann,
irgendwas,
äh,
Users,
äh,
Users 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,
äh,
also Users von Create.
Streng genommen ist es,
äh,
naja,
Objects Create,
äh,
das ist halt der,
der Model Manager,
auf den man das aufruft,
aber das ist halt dann ein,
ein Ding,
aber dieses Objects ist halt,
ja,
das ist ein bisschen komplizierter,
aber dieses Objects ist auf jeden Fall,
äh,
ein Ding,
was an der Klasse hängt,
von,
äh,
an der,
und,
ähm,
äh,
äh,
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 Instanz und die eine Teile repräsentiert,
weil,
ja,
innerhalb von der einen Zeile sich selber irgendwie,
ranzuhängen würde gar nicht so richtig funktionieren.
Ja,
könnte man auch machen,
wäre,
wäre irgendwie komisch,
ähm,
und,
warum nimmt man das aber?
Dafür ist nicht einfach eine Static Method.
Ja,
äh,
könnte man auch,
aber,
das,
nee,
kann man nicht,
weil,
dann,
würde man halt zum Beispiel nicht mehr wissen,
was sind denn jetzt die ganzen Felder,
die Tabelle wahrscheinlich,
genau,
man müsste ja auch wissen,
welche Attribute gibt es,
was muss ich eigentlich da,
und so,
das,
ähm,
ja,
das muss man ja auch,
welche Tabelle ist denn das überhaupt,
wo steht die in der Datenbank,
und das hängt halt an der,
das sind Informationen,
die an der Klasse dranhängen,
und,
ähm,
ja.
Das heißt,
die Static Method,
ich würde mir sowas sagen,
wie,
ähm,
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,
ja,
also hier hast du einen String,
mach mir mal einen Hash davon,
den ich dann irgendwie in die Datenbank schreibe.
Mhm.
Da,
das braucht gar keinen Kontext,
ja,
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,
äh,
ein User eingibt,
und die dann halt irgendwie gehasht werden sollen.
Also,
das,
so könnte man das machen.
Jetzt haben wir noch Property.
Äh,
Property-Dekorator,
ja,
der ist,
äh,
da geht's eigentlich nur darum,
dass man,
ähm,
ja,
so ein bisschen Convenience,
dass man dann nicht eine Methode aufruft,
sondern,
also man,
man schreibt halt,
äh,
also der häufigste Fall ist,
man hat,
äh,
eine Methode,
die nennt man so wie ein Attribut,
und schreibt dann AddProperty drüber,
äh,
und dann,
äh,
wird halt diese Methode aufgerufen,
wenn man irgendwo sagt,
Instanz.
Punkt,
äh,
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,
äh,
verwenden will,
äh,
Klammer auf Klammer zusagen,
was halt so ein bisschen sinnlos ist,
wenn man zum Beispiel gar nichts übergeben möchte,
äh,
Argumenten,
und,
ähm,
vielleicht auch etwas ist,
was halt,
äh,
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,
ähm,
Oh,
das ist quasi ein getarntes Methodending.
Ja,
ist so manchmal ein bisschen,
also das ist auch so,
so,
diese Dekorator-Geschichte ist so manchmal ein bisschen,
ähm,
also,
im,
auf Python steht ja sowas,
explizit ist besser als implizit,
ne,
und das ist halt schon ganz schön implizit,
dass wenn man jetzt irgendwo,
äh,
eben,
Instanz,
äh,
X.
Punkt Huber sagt,
halt dann irgendwie,
ein Code ausgeführt wird,
der irgendwas ausrechnet,
und dann unter Umständen auch sehr langsam sein kann,
oder was auch immer,
das ist halt nicht 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,
ähm,
ja,
es ist eigentlich normalerweise,
wenn man dann komplizierte Sachen macht,
dann sollte man das vielleicht dann auch eher als Methode hinschreiben,
und dann,
äh,
wird das dann vielleicht klarer,
ja,
also.
Aber wenn man kurz vielleicht,
äh,
zwei Attribute hat,
wie das eine ist Kosten,
das andere ist Umsatz,
und dann will man den Gewinn ausrechnen,
und dann kann man vielleicht schon eine Funktion machen,
die dann einfach kurz als,
äh,
Property sagt hier,
äh,
Umsatz,
äh,
Gewinn,
und dann,
genau.
Und,
ähm,
ja,
also,
äh,
man,
und das,
also das Get,
äh,
zu implementieren ist ja sehr leicht,
man schreibt irgendwie der Property drüber,
und dann war's das.
Äh,
das Set geht auch,
also man kann das auch so machen,
dass dann halt ein Setter aufgerufen wird,
wenn man sagt irgendwas,
in Instance X.fuba gleich irgendwie,
das ist ein bisschen komplizierter,
aber,
äh,
ja,
geht auch so ähnlich,
ähm,
kann man irgendwie sagen,
so,
das ist hier der Getter,
das ist hier der Setter,
oder was,
ach,
ich weiß nicht genau.
Kann man dann nachgucken,
wenn man's braucht.
Braucht man selten.
Also ich hab's ein paar Mal benutzt,
aber nicht oft.
Aber,
äh,
überhaupt das Konzept von,
von Dekoratoren.
Das ist immer ganz gut.
Getter Setter bedeutet halt,
dass man die Attribute irgendwie von außen dann beeinflussen,
setzen,
von der Instanz setzt,
äh,
bekommt oder setzt,
äh,
genau,
und zwar nicht direkt manipuliert,
sondern,
halt,
äh,
Methoden dafür aufruft,
die dann noch irgendwas vorher und hinterher tun.
Jetzt haben wir schon ungefähr 50 Mal Dekorator gesagt,
und du wolltest eigentlich noch irgendwas anderes,
ähm,
vorher sagen.
Dann muss man vielleicht nochmal erklären,
was ein Dekorator eigentlich ist.
Eigentlich ist es eine sehr,
äh,
nicht so,
äh,
nicht so,
äh,
na,
es kann,
es kann leicht kompliziert werden.
Trick, Trick.
Äh,
ja,
es ist auf der einen Seite ein bisschen Spezialsyntax,
ähm,
äh,
diese Geschichte mit dem Ad-Symbol,
dass man halt über Klassen und über Methoden,
Funktionen schreiben kann,
äh,
auf der anderen Seite ist es,
ähm,
man könnte es,
so anders hinschreiben,
und da bräuchte man diese Spezialsyntax nicht,
also die haben das so ein bisschen vereinfacht,
man könnte halt auch hinschreiben,
äh,
irgendwie x gleich,
ähm,
wrap mir mal eine andere Funktion,
wrap,
Klammer auf,
irgendwie eine andere Funktion,
Klammer zu,
und dann wäre das die dekorierte,
ja,
x die dekorierte Funktion,
also,
äh,
man macht sich eine Tapete auf die Wand,
und unter der sieht man dann halt hier Sachen anders.
Ah,
die Form bleibt erhalten,
damit ist dann vielleicht rot oder blau.
Ja,
äh,
also die Idee ist sozusagen,
dass man,
äh,
äh,
etwas macht,
also man halt Code hat,
der,
ja,
man packt,
deswegen ist Dekorator eigentlich auch ein,
der zeichnet ziemlich genau,
was es tut,
äh,
man hat halt,
Code und Output,
der rauskommt,
oder beziehungsweise reingeht,
wird,
wird nochmal,
geht nochmal durch anderen Code durch,
und dann,
äh,
sozusagen man kann halt,
bevor irgendwas,
bevor die Funktion aufgerufen wird,
irgendwie Dinge damit tun,
und,
ähm,
hinterher Dinge mit dem,
das wird aber langsam,
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,
äh,
also,
äh,
und 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,
ähm,
äh,
tatsächlich,
äh,
genau,
äh,
nicht,
nicht wirklich,
wenn man Dekoratoren schreibt,
nicht,
das selber machen eigentlich,
sondern man sollte aus,
für den Funktools,
Raps,
oder so nehmen,
nehmen,
und,
ähm,
weil,
es gibt noch so ein paar Hakeligkeiten,
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's halt,
ähm,
eben in den Funktools,
gibt's da,
glaube ich,
äh,
irgendwie,
ähm,
ähm,
Funktionen,
die,
wenn man die benutzt,
um den Dekorator zu bauen,
dann kümmern die sich um diesen Kram,
sodass halt dann,
wenn man Tracebacks weiter in die Namen sieht,
und so,
also das ist ein bisschen,
das hat das jetzt mit so einem Kontext zu tun,
Kontextmanager,
oder so was,
das ist,
oh,
nee,
das hat aber nichts zu tun,
das ist so eine arme Geschichte,
das hört sich so ein bisschen an,
als macht man irgendwie so einen Kontext auf,
und rappt irgendwas,
und gibt das dann wieder,
baut das dann am Ende wieder auseinander,
mhm,
also,
ja,
also,
was eventuell irgendwie,
eine Gemeinsamkeit ist,
dass beides irgendwie unten drunter,
vielleicht Closure ist verwendet,
als,
äh,
wie das umgesetzt ist,
aber,
äh,
ja,
das ist sozusagen eine,
mhm,
eine,
eine,
eine,
eine,
eine interne Funktion,
die halt,
äh,
zurückgegeben wird,
und die halt,
das ist ja auch so der Trick,
wie man das hinkriegt,
dass der,
äh,
Scope,
äh,
dass man halt auf die Sachen zugreifen kann,
die im Scope der Funktion sind,
dass man halt sozusagen,
äh,
äh,
naja,
das ist zu kompliziert,
das kann man alles nicht so,
das ist auch nicht anfängermäßig,
das kann man nicht gut erklären,
da muss man sich einfach mal,
äh,
also ich würde sagen,
also ein Tipp ist,
äh,
sich das,
wenn man,
wenn man die Kraton schreiben will,
äh,
äh,
aus den Functools,
äh,
die Reps-Funktion zu nehmen,
und,
ähm,
ja,
einfach mal so ein bisschen damit rumzuspielen,
man braucht ein bisschen,
bis das irgendwie,
äh,
bis man das so raus hat,
ja,
ähm,
genau,
aber dafür sind Dekoratoren da,
also,
man kann damit ganz nette Sachen machen,
wie zum Beispiel,
also,
wenn man einfach nur wissen will,
wofür braucht man solche Sachen eigentlich,
äh,
wenn man,
ähm,
ja,
zum Beispiel eben wieder Datenbankgeschichte,
kann man sagen,
okay,
äh,
gibt's einen Transaktionsdekorator,
ne,
da,
da,
schreibt man einfach drüber,
äh,
Transaction Atomic,
genau,
das hier ist jetzt alles in einer Transaktion,
und das,
alle Schritte gehen zusammen gut,
oder gar nicht,
und wenn halt zwischendurch irgendwas,
äh,
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's nämlich auch den Kontextmanager,
man kann auch sagen,
with a Transaction Atomic,
ja,
ja,
ja,
genau,
ja,
es ist,
äh,
klar,
kann man auch machen,
ja,
ähm,
ja,
äh,
das,
äh,
genau,
das ist eine,
eine Geschichte,
ansonsten,
ja,
man kann auch Dekoratoren dafür benutzen,
um sich jetzt eine bestimmte Datenbankverwendung immer reinzuholen,
in eine Funktion,
ja,
da werden wir jetzt gerade über Tango reden,
da wird das ja auch benutzt,
zum Beispiel für,
um Funktionen zu dekorieren,
Login Required,
dass man halt irgendwie eingeloggt im Benutzer sein muss,
das heißt,
ähm,
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 ein,
äh,
Subklasse einer Klasse,
die man benutzt,
und bestimmte Attribute zusätzlich dazu.
Ja,
Mix-In ist dann so ein bisschen eben,
wie man,
äh,
Code,
äh,
wiederverwenden kann,
in Klassen,
ohne erben zu müssen,
weil erben macht natürlich,
das ist ja sozusagen ein ganz klassischer Weg,
und das kann man natürlich auch tun.
Ja,
also in gewisser Weise ist es ja eine Form von vererben,
also aber eine generalisierte Form,
die irgendwie jetzt nicht genau mit der ursprünglichen Klasse zu tun hat,
sondern,
ja,
genau,
also du kannst halt,
ist es nicht so,
dass du,
äh,
ja,
also zwei unterschiedliche Klassen,
die nichts miteinander zu tun haben,
ganz unterschiedliche Stellen,
ähm,
in der Klassenhierarchie sind,
können halt das gleiche Mix-In verwenden.
Das ist cool,
das ist so ein bisschen wie,
wie Genetik,
du kannst dem Frosch Flügel geben,
oder so.
Ja.
Das ist,
äh,
ja,
ja,
warum auch nicht.
Ja,
wenn du Sachen hat,
die Flügel haben wollen,
man hat irgendwie eine Klasse,
die Flügel bereitstellt,
dann kann man diese Flügel jeder Klasse geben,
und jetzt.
Ja,
ja,
macht,
macht natürlich auch nicht immer irgendwie Sinn,
aber,
äh,
also,
also,
äh,
Vererbung ist auch so ein problematisches Geschirr,
das ist immer das,
was einem,
äh,
wenn man sich mit objektorientierter Programmierung beschäftigt,
irgendwie so gesagt wird,
wie man das tun soll,
oder so am Anfang,
keine Ahnung,
jedenfalls,
weil wir,
vielleicht ist es mittlerweile auch besser geworden,
ähm,
dass man halt Sachen von Dingen dann erbt,
ne,
dass man halt,
äh,
keine Ahnung,
äh,
ja,
äh,
weiß ich nicht,
da wird immer mit solchen Beispielen gearbeitet,
was,
äh,
äh,
äh,
dass man,
irgendwie,
keine Ahnung,
meistens irgendwelche geometrischen Formen,
oder sowas,
ne,
irgendwie,
wenn man jetzt,
äh,
ein rechtwinkliges Dreieck hat,
dann ist das auf jeden Fall schon mal ein Dreieck,
ne,
und ein Dreieck ist irgendwas,
was halt irgendwie,
ja,
ich finde das ganz,
ganz schlecht,
das nämlich dem Gradius auch vorzustellen,
ne,
also die geometrische Formen sind zwar ganz,
okay,
aber vielleicht auch mit dieser,
ähm,
Universums,
äh,
Geschichte,
du hast irgendwo ein großes,
schwarzes Loch,
so den Urknall,
oder sowas,
und ein Objekt,
äh,
orbitet da irgendwie herum,
das ist jetzt vielleicht schon mal so eine Galaxie,
und dann,
äh,
das ist also die,
die Subklasse wäre es halt Universum,
ne,
das wäre so die Basisklasse,
von der alles irgendwie erbt,
alles ist irgendwie so ein Ding,
das ist ein bisschen groß,
ja,
dann hast du halt eine Galaxie,
das ist vielleicht schon mal das erste kleine Ding,
dann,
oh,
okay,
in der Galaxie gibt es ein Sonnensystem,
ein Sonnensystem ist auf jeden Fall Teil einer Galaxie,
dann gelten halt die gleichen Gesetze,
physikalischen Gesetze,
und hast du 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,
äh,
ne,
gleiche Grundlagen,
und Planeten können jetzt aber verschiedene Dinge besonders machen.
Äh,
ja,
aber ich glaube,
ich fürchte,
also,
das wird auch,
also,
mit solchen Dingen,
ich glaube,
dass Leute versuchen,
irgendwie so Alltags-Ontologie,
irgendwie,
äh,
aber das Problem ist,
das passt ja schon,
also,
weil dieser Planet,
der orbitet ja,
ne,
dieser,
diesem Stern,
und der Stern,
der orbitet ja dem Zentrum dieser Galaxis,
so,
ja,
dann wäre sozusagen die allgemeinste Oberklasse,
wäre sowas wie Himmelskörper,
oder sowas,
oder keine Ahnung,
ne,
ne,
ne,
ne,
ne,
ne,
ne,
ne,
ne,
ich glaube,
das,
das ist gar nicht so,
also,
Himmelskörper-Objekt,
na,
ich weiß nicht,
also,
du brauchst ja schon ein Orbit,
das ist ja Grundeinkommen,
ja,
aber,
aber,
ich würde nicht,
ich würde,
also,
das,
ich will immer,
ich will in die Erbung so ein bisschen gucken,
oder?
Ich,
ich will,
dass das immer wieder passiert,
und das soll ich,
Leute,
dass das versucht wird,
das so zu beschreiben,
und ich finde,
das ist nicht hilfreich,
weil,
ähm,
das Mond,
dann geht ein Planet,
ja,
du machst ja irgendwie immer so eine Basisklasse,
ja,
und die Basisklasse vom Mond wäre jetzt der 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,
genau solche Sachen will man eigentlich nicht machen,
also,
das ist genau das,
was ich,
äh,
also,
äh,
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 so zu applizieren,
sondern es geht tatsächlich darum,
dass man Sachen programmieren kann,
und das ist,
ähm,
das ist oft nicht so,
wie,
äh,
das ist halt anders,
das ist nicht so,
wie die Welt da draußen,
das ist schwer,
oder so,
man eigentlich,
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 hab da Schwierigkeiten mit,
äh,
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,
äh,
richtig und wichtig ist,
aber,
die sind selten,
und,
äh,
was einem aber erklärt wird,
ist,
dass das der Normalfall,
so macht man das halt,
und 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 das sinnvoll ist,
aber,
das ist nicht so,
dass man das immer machen,
so,
oder normalerweise so machen sollte,
sondern das ist halt eher die Ausnahme,
normalerweise sollte man,
wenn man zum Beispiel Code,
in zwei Klassen wiederverwenden will,
dann macht man halt Mixin,
und nicht diese Vererbung,
weil,
das ist halt,
das ist auch am Anfang,
das geht,
geht ganz gut,
und sobald es komplizierter wird,
hat man da große Probleme,
weil du dann,
deine,
deine Hierarchie,
die muss halt einfach stimmen,
die muss halt passen auf dein Problem,
das kannst du hinterher nicht mehr gut,
äh,
ändern,
und hinterher gut anpassen,
das 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 meistens gar nicht genau kennt.
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,
äh,
programmiere,
dann habe ich halt Funktionen,
die ich aufrufe,
und,
äh,
wenn ich jetzt merke,
ich benutze den gleichen Code an drei,
vier unterschiedlichen Stellen,
ja,
dann,
äh,
mache ich halt eine Funktion drauf,
äh,
oder draußen rufe den an den Stellen,
wo ich,
äh,
sozusagen den,
das verwenden möchte,
den Code einfach auf,
anstelle,
dass ich den Code aber entstehen habe.
Und genauso kann man das mit Klassen im Grunde auch machen,
und,
äh,
Code,
den ich in mehreren Klassen benutze,
den ziehe ich halt in Mixins raus.
Und dann ist es relativ easy,
weil,
äh,
ja,
äh,
die,
diese Mixins machen halt nichts anderes,
außer,
äh,
irgendwie halt eine Methode sozusagen zu,
hinzuzufügen zu einer Klasse.
Und,
ähm,
ja,
ähm,
während so Vererbungen,
hm,
ja,
also es macht halt mehr.
Das tut mehr,
also was soll,
also es gibt halt dann diese Basis,
ne,
Basisklassen,
Basis oder sowas,
oder es gibt noch sowas wie,
ähm,
Message Resolution Order,
MROs,
wo man dann gucken kann,
welche Methode in welcher Reihenfolge aufrufen werden,
weil die sich ja gegenseitig überschreiben können.
Und,
ähm,
das Problem,
was man dann hat irgendwann ist,
ist, dass wenn man da,
wie du sagst,
einen Fehler macht,
dann hat man Zirkelvererbung oder sowas.
Und das sollte man wahrscheinlich nicht verwehren.
Ja,
das passieren halt,
äh,
genau,
wenn man irgendwas falsch macht,
dann passieren unerwartete Dinge,
die man auch nicht so,
die nicht so offensichtlich sind.
Und,
äh,
ja,
und es kann auch sehr schnell sehr hässlich werden.
Also,
ähm,
es gibt wenig Fälle,
wo das eine super sinnvolle Geschichte ist.
Das ist aber 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,
äh,
ganz viele Dekoratoren machen will,
ganz viele Vererbungen
und am besten das Ganze irgendwie
in verschachtelte List-Comprehensions-Fakt oder so.
Und mit abstrakten Metaklassen bitte?
Ja,
Metaklassen,
oh ja,
mhm,
äh,
aber,
äh,
ich weiß nicht,
vielleicht keine gute Idee.
Also jedenfalls nicht am Anfang.
Also,
ähm,
wenn man,
wenn man dann irgendwann genau weiß,
welches Problem man lösen möchte
und man möchte halt ein Framework bauen,
das halt,
wo man dann,
also nehmen wir irgendwie sowas wie General Rest Framework,
finde ich das relativ gelungen.
Äh,
da,
äh,
kann man oft viel Funktionalität,
äh,
abbilden,
dadurch,
dass man jetzt sozusagen von irgendeiner,
von irgendeinem Viewset oder so erbt
und dann überschreiten wir 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,
ähm,
wenn man so anfängt,
dann,
äh,
üblicherweise landet man relativ,
äh,
schnell in einem ziemlich üblen Zustand.
In Teufelsküche,
in der Schlangengrube.
Ja,
ja,
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
Klassengerecht hinbauen und so,
aber am Anfang,
äh,
lieber nicht.
Ich glaube,
das ist jetzt der richtige Ort für die nächste Frage,
ähm,
die wäre,
was ist ein Monkey Patch?
Äh,
ja,
das ist,
da das alles Objekte sind in Python,
ähm,
kann man die natürlich,
und die alle dynamisch,
äh,
änderbar sind,
äh,
kann man ja auch,
äh,
sozusagen einfach die Methode,
äh,
einer,
eines Objektes einfach,
man kann ja sagen,
zum Beispiel,
wenn ich da,
äh,
nicht nur Attribute setzen,
sondern ich kann auch die Methode einfach überschreiben.
Ich könnte zum Beispiel sagen,
wenn ich meinen Barbaren habe,
ne,
von dem wir eben geredet haben,
und er hat,
äh,
einen Attribut,
das heißt Attacke,
und da ist immer irgendwas drauf,
dann kann ich einfach die überschreiben,
und dann macht er bei der Attacke irgendwas anderes,
zum Beispiel heilte ich,
oder so.
Genau,
genau,
und ich könnte einfach sagen,
äh,
ja,
äh,
äh,
barbar.attack gleich Lambda X,
äh,
YZ,
was auch immer da übergeben wird.
Das wäre zum Beispiel wahrscheinlich die Möglichkeit,
wie man,
ähm,
Vererbung bei Klassen richtig macht,
indem man die Basisklasse hat,
die wäre jetzt,
ähm,
wahrscheinlich in so einem Rollenspiel,
sowas wie eine Person,
und dann vererbt man dann auch verschiedene,
äh,
weiß ich nicht,
äh,
Rassen,
zum Beispiel Echse,
oder Mensch,
oder sowas.
Na,
ne,
ich bin 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,
äh,
überschreiben.
Überschreibt man dann.
Ja.
Ja,
aber das ist halt sehr verführerisch,
dass man halt ein Bild davon hat,
wie das,
äh,
wie,
wie sozusagen die Welt,
die man im Spiel bauen will,
äh,
aufgebaut ist,
aber tatsächlich ist das zu programmieren oft was anderes,
als nur diese Welt zu modellieren,
und dann,
das ist nicht das,
oder jedenfalls,
meine Erfahrung ist so,
dass,
wenn man das so versucht zu modellieren,
wie man sich das vorstellt,
dann,
äh,
passt es nicht so gut auf das,
wie man das programmieren will.
Sondern,
es ist halt einfach,
ja,
es ist,
äh,
ist.
Aber das zu verstehen,
das ist,
das ist vielleicht schwierig,
also für jemanden,
der das nicht weiß,
warum,
wieso,
warum man das dann einfach nicht macht,
obwohl das ja so intuitiv,
endlich ja so einen Zugang dazu gibt.
Ja,
genau,
also ich,
ich,
das ist,
das ist halt,
wie,
wie,
es gibt da auch immer diesen Spruch,
ne,
es gibt für jedes Problem eine Lösung,
die ist,
äh,
einfach,
leicht zu verstehen,
äh,
elegant und falsch.
Das ist halt auch immer,
und ich,
was mich ärgert so ein bisschen,
ist,
dass es halt auch immer so Programmier-,
Lehrbüchern oder so oft so,
oder schlimm ist es,
äh,
ja,
wenn Leute programmieren,
äh,
erklären,
dann vielleicht gar nicht selber so,
äh,
da drin stecken,
dann machen die das oft so,
dann fangen die da 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,
das,
da liegt kein Segen drauf,
das,
das funktioniert so nicht,
ähm,
äh,
ja.
Naja.
Ja.
Also,
ihr seht schon,
wenn ihr über die Schlangengrube drüber wollt,
dann ist da manchmal so ein bisschen,
ja,
Indiana Jones-Seit hängt von der Decke,
rüber schwingen,
juhu.
Ich,
ich würde,
ich,
so,
also so Ratschlag wäre halt eher,
ist versuchen,
einfach zu halten,
nicht so komplizierte Sachen,
ganz komplizierten Sprachwitscher,
vielleicht nicht so viel zu verwenden,
äh,
oder,
äh,
das ein bisschen hinaus zu zögern,
ja,
ich verstehe natürlich,
dass das immer so ein bisschen auch reizvoll ist,
äh,
aber,
ja,
ja,
und nicht,
nicht irgendwie so,
wenn,
wenn so Dinge,
die so aussehen,
als wie die Weltformel,
die alles löst,
mhm,
mhm,
das ist ja skeptisch sein.
Ja,
dann machen wir direkt wieder mit einfachen Dingen weiter,
ähm,
was ist denn,
ähm,
was sind denn Argumente,
oder Keyword-Argumente,
was sind Args und Quarks?
Ah,
ja,
ja,
ja,
ja,
das ist auch etwas,
was immer ein bisschen verwirrend ist,
äh,
ja,
also Funktionen,
Methoden,
äh,
haben,
haben Argumente,
das heißt Dinge,
die man übergeben kann,
äh,
mhm,
äh,
ganz normale Positionsargumente sind halt sozusagen das,
äh,
das Übliche irgendwie,
die haben halt einen fest,
die sind an einer festen 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,
die,
äh,
wo man dann explizit dazu sagt,
äh,
welches,
ähm,
welches Argument man denn jetzt gemeint hat,
sozusagen,
das schreibt man dann halt sowohl in die,
äh,
Funktionsdefinitionen rein,
als auch dann,
äh,
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,
mhm,
da können dann komische Sachen passieren,
und dann ist es auch so,
dass man,
äh,
wenn man sich,
äh,
wenn man jetzt eine Liste von Argumenten übergibt,
äh,
ähm,
dann kann man die natürlich alle einzeln übergeben,
man kann die aber auch insgesamt übergeben.
Mit Stähnchen dann,
oder mit Stähnchen,
Stähnchen,
also wenn man die Liste hat in der Hand,
äh,
wenn man eine Liste hat oder Tupel,
dann kann man einfach einen Stern davor schreiben,
und dann wird das automatisch sozusagen als,
äh,
ja,
Argumente dann übergeben,
das heißt,
man sagt dann irgendwie,
äh,
Funktion,
Klammer auf,
Stern,
und dann eben,
Args,
Argumente,
oder wie auch immer das,
die,
die Items,
diese Struktur heißt,
die man jetzt gerade in der Hand hat,
Klammer zu,
und dann,
äh,
kann man in der Funktionsdefinition drinstehen haben,
sowas,
Def-Funktion,
Klammer auf,
A,
Komma B,
Komma C,
und,
äh,
ja,
muss dann natürlich alles irgendwie stimmen von der Anzahl und so,
aber, äh,
das passiert dann automatisch.
Ich finde das bei Keyword-Argumenten relativ witzig,
weil da kann man alle viele Sachen,
die man irgendwie zugewiesen hat,
Ja.
irgendwie in eine Liste packen,
genau,
das,
eben,
bei normalen Positionsargumenten ist es halt,
äh,
entweder man übergibt sie per Position,
oder Stern,
äh,
kann auch eben in der Funktionsdefinition sagen,
so,
das können jetzt hier beliebig viele sein,
dann schreibt man halt nicht A,
Komma B,
Komma C rein,
sondern Stern,
Args,
Komma,
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 Perl oder so,
gibt das nur so,
äh,
das geht in Python auch,
ist da aber ein Spezialfall,
ähm,
oder,
äh,
genau,
und das Ganze geht mit Keyword-Argumenten genauso,
nur dass dann halt nicht Stern ist,
sondern Stern,
Stern,
und damit lassen sich halt sehr,
sehr leicht,
ähm,
zum Beispiel Dicts in,
äh,
Keyword-Argumente verwandeln,
und Keyword-Argumente in Dicts,
was halt manchmal sehr praktisch ist,
ja,
äh,
und eine Vielschreibarbeit auch Sport,
ja.
Cool.
Jetzt haben wir noch zwei Sachen,
die noch ein bisschen in diese Funktionen reingehen,
zweimal,
wir haben ja Funktionen,
jetzt jede Menge so Sachen,
ähm,
dann,
was ist eine Lambda-Funktion,
was macht die denn dann?
Haben wir,
glaube ich,
auch schon einmal kurz besprochen,
aber,
äh,
mhm,
ist eigentlich nichts Besonderes,
ist,
äh,
eine Funktion wie jede andere,
also was halt in Python nicht so richtig schick geht,
ich meine ja auch,
äh,
ein bisschen JavaScript,
und das ist da so schon ein Stückchen,
äh,
eleganter vielleicht,
äh,
oder,
also was es in Python so nicht gibt,
sind so anonyme Blöcke,
oder anonyme Funktionen,
über mehrere Zeilen,
oder sowas,
sondern da gibt's halt Lambda,
äh,
äh,
äh,
also der,
warum muss das überhaupt sein,
wofür braucht man sowas?
Ja,
es gibt oft,
äh,
irgendwie Situationen,
wo man,
eine Funktion übergeben möchte,
äh,
irgendwo hin,
aber die sonst nicht braucht.
Also,
ähm,
ein Beispiel wäre jetzt,
irgendwie,
wenn man,
äh,
irgendwas mit,
mit,
äh,
mit NumPy-Arrays macht,
oder so,
oder,
oder DataFrames,
äh,
da ist es ja so,
dass man eigentlich keine Vorschleifen,
äh,
nicht per Vorschleife,
über irgendwas iterieren,
äh,
kann,
weil Vorschleifen super langsam sind,
im Fallen.
Ja,
das jetzt nicht heißen soll,
das finde ich nicht,
weil,
so,
äh,
Vorschleifen sind halt schon gut,
aber wenn man jetzt über eine,
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,
aber die man ja nicht hinschreiben kann.
Diese Funktion hat aber sonst keinen Zweck,
die ist nicht,
die,
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 mit dieser Vorschleife macht,
halt machen,
aber das geht halt nicht,
daher,
äh,
ja,
braucht man halt jetzt diese temporäre Funktion,
der man jetzt auch gar keinen,
gar nicht unbedingt einen Namen geben will,
weil,
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,
äh,
genau.
Lambda,
äh,
gibt halt sozusagen,
also Lambda X,
Doppelpunkt,
äh,
äh,
X,
äh,
zum Quadrat oder sowas,
würde halt,
ein Argument nehmen,
und dieses Argument mit sich selbst multiplizieren,
und dann wieder zurückgeben.
Nur,
dass man halt,
äh,
das Return weglassen,
muss,
also Return kann man nicht hinschreiben,
in der Lambda,
sondern ist es halt,
das,
was halt man,
das Letzte,
was irgendwie,
das ist implizit,
nicht explizit,
ja,
implizit wird das halt einfach zurückgegeben.
Und,
äh,
ja,
auch der,
äh,
die,
die Argumentübergabe ist ein bisschen anders,
ne,
es ist halt nicht irgendwie Klammer auf,
und dann,
sowas,
sondern es ist halt einfach Leerzeichen,
und dann Liste der,
Argumente,
Doppelpunkt,
äh,
und das wird halt implizit,
äh,
passiert das halt,
und es kann alles nur in einer Zeile stehen,
es darf nicht,
äh,
darf nicht mehrere Zeilen.
Aber so ein bisschen hässlich ist es aber doch.
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.
Kann man ja auch sagen,
irgendwie,
äh,
rechne mir,
irgendwie das Quadrat aus,
oder so,
äh,
Funktion,
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,
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 auch nicht,
Das heißt,
Lambda braucht man eigentlich überhaupt nicht,
weil das irgendwie,
Nee,
man braucht es,
braucht es nicht,
äh,
ist es halt manchmal auch,
äh,
nett,
das so hinschreiben zu können,
aber wirklich brauchen tut man es nicht,
nee.
Ähm,
Spart ein bisschen Schreibarbeit,
für zum Beispiel so einfache Operationen,
wie einfach Quadrat zu geben,
dann kann man einfach das Lambda in die Teile schreiben,
wenn man es nicht wieder sonst braucht,
dann.
Genau,
weil du hast halt,
äh,
wenn du,
wenn du Funktionen hinschreibst in Python,
immer einen gewissen Zeilen-Overhead,
weil,
äh,
naja,
da,
da,
da,
da die,
da die Umbrüche,
äh,
syntaktisch relevant sind,
und die Eindrückung,
äh,
ist es halt so,
dass du da auf jeden Fall immer mehrere,
mindestens mal zwei Zeilen für hinschreiben musst,
ja,
und mit Lambda kannst du es auch in einer Zeile hinschreiben.
Und wenn das wirklich eine ganz simple Geschichte ist,
dann,
äh,
willst du vielleicht keine,
nicht deswegen eine Funktion definieren,
sondern,
ja,
aber,
äh,
letztlich kann man dafür auch ganz normale Funktionen verwenden,
ähm,
und,
äh,
was ja an Python auch geht,
was auch schön ist,
du kannst halt,
äh,
innerhalb von Funktionen auch wieder Funktionen definieren,
ne,
also,
du musst ja nicht die Funktionen dann außerhalb der Funktionen,
das heißt,
du kannst die Funktionen auch direkt da an die Stelle schreiben,
wo du sie verwenden willst.
Wann macht man das denn,
also,
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 Clojure,
äh,
Clojures,
brauchst du das halt,
wo du eine Funktion zurückgibst,
die halt Zugriff auf den Scope,
äh,
äh,
auf Variablen hat,
die im Scope dieser Funktion liegen.
Ja,
also,
wenn du,
ähm,
also Clojure ist quasi,
sozusagen,
du hast eine Funktion,
und in dieser Funktion gibst du jetzt,
du gibst jetzt eine andere Funktion zurück.
Eine innere,
äh,
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 einen Counter,
der mit irgendwas initialisiert wird.
Also,
genau,
das Beispiel können wir mal nehmen,
sagen wir mal,
def,
äh,
äh,
äh,
äh,
äh,
äh,
äh,
äh,
äh,
äh,
äh,
äh,
äh,
äh,
äh,
äh,
äh,
äh,
äh,
äh,
äh,
äh,
äh,
äh,
äh,
äh,
Y
Klammer zu, Doppelpunkt
und dann
Return
Range
Counter,
Counter,
Y oder so.
Es geht darum, 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,
darauf 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.
Und das ist eine Closure.
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 Counterwert
nicht mehr ran.
Und dann kann ich halt die äußere Funktion verwenden, um sozusagen
einen Counter, der ab 5 zählt, immer zurück.
Oder gib mir einen Counter, der ab 10 zählt, immer.
Und das 10 oder 5 steht dann halt eben in dieser
Ja, ist ein etwas
komplizierteres Konzept.
Aber das ist halt auch die Art, wie dann irgendwie
Dekoratoren und
Context Manager und so funktionieren.
Die haben da
Dinge in der Richtung.
Ja.
Genau. Aber das ist eigentlich,
das finde ich auch sehr schön, dass man halt
in Funktionen auch locker
Funktionen definieren kann. Und man kann auch Klassen innerhalb von Klassen
definieren und so. Also das geht
einfach problemlos.
Klingt nach viel Konfusion
für die Anfängerkurve, die jetzt gerade da ist.
Ja, ja, ja. Vielleicht sollte man, genau,
vielleicht sollte man das natürlich auch.
Ja.
Ich habe jetzt noch eine Basisfrage.
Was ist der Unterschied von einer
Zugreifung von gleich gleich oder ist, also
nicht zugreifend, sondern eine Abfrage.
Würdest du jetzt etwas vergleichen, ein gleich gleich oder ein ist?
Also zum Beispiel A gleich gleich B, A ist B.
Etwas ist gleich gleich None.
Ist None.
Ja.
Ähm, also
äh, wenn
ich gleich gleich verwendere,
also gleich ist natürlich irgendwie
Zuweisung, aber gleich gleich,
da wird halt der Wert verglichen.
Also, ähm,
und bei ist wird
verglichen, ob es das gleiche Objekt ist.
Und deswegen zahlt man zum Beispiel
bei None, sagt man immer ist None, weil
es nur ein None-Objekt gibt. Genau.
None ist ein Singleton. Ja.
Ja. Und deswegen kann ich halt
so testen,
äh, ob es wirklich None ist.
True und False sind auch Singleton.
Äh.
Hm.
Hm.
Ja, ich, äh,
bin ich mir jetzt nicht so ganz sicher, aber ich glaube schon.
Äh, ich weiß
aber nicht genau. Ja, so müsste wahrscheinlich
so sein, ne? Das könnte eigentlich gar nicht anders.
Okay, das heißt, ihr müsst halt tatsächlich,
wenn es ist, immer genau das Objekt.
Das heißt, man kann...
Ja, ja, aber man kann das auch zuweisen.
Ja.
Also es ist auch ganz böse. Man kann
True und False auch noch anders belegen. Also,
hm, müsste man mal nachgucken.
Ja, das, 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 in Python irgendwelche Objekte sind,
irgendwelche Typen sind. Und dann, ähm, da habe ich mich
irgendwie gefragt, ob, äh,
jetzt nicht die ganzen Zuweisungen, also man kann jetzt irgendwie Typen umwandeln,
ja, also, ne, von Integer auf String oder sowas.
Ja. Ob das nicht halt auch, äh,
Klasse dann eigentlich ist, die man halt
nimmt, weil das halt ein Typ ist, ein Objekt ist.
Deswegen müsste das 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
in eine Instanz eines Objektes Integer wechselt.
Wenn man ein Int vorstellt, es müsste ein bisschen großes Int sein,
dann an der Stelle irgendwie, war ich da ein bisschen verwirrt.
Ja, ich, äh, also,
da, ich rate jetzt mal, woher das kommt.
Ich weiß es ehrlich gesagt auch nicht so genau.
Ähm, vielleicht weiß das jemand
besser und kann mich da korrigieren, aber ich
denke mal, das liegt daran, dass
das Build-Ins sind.
Also ja, eigentlich
die Konvention in Python ist so, wenn das eine Klasse ist,
dann schreibt man das halt groß.
Ja, aber, äh,
ich glaube, alle Build-Ins sind klein.
Und da das Build-Ins sind,
äh,
wird die Konvention...
Das ist wichtiger, weil es gibt nicht so viele Build-Ins.
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,
eine neue oder eine andere Klasse erzeugt.
Jaja, das ist so, aber das passiert auch tatsächlich.
Also wenn ich sage int, Klammer auf,
5, Klammer zu,
dann wird ein neues Int,
Job-Objekt erzeugt, genau, mit dem Wort 5.
Ähm, also es ist tatsächlich,
ähm, ja, äh,
auch Dict ist ja in, äh,
ist ja eine Klasse tatsächlich.
Ich kann ja auch davon erben und so, sollte ich vielleicht nicht machen, aber,
äh, auch da, aber
ich kann davon erben und das funktioniert auch.
Ähm,
aber ja, aber ich denke, das 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.
Ähm, zum Beispiel
für, für, für, äh,
äh, Dict und List und so
gibt es User-Dict, User-List.
Und, äh, auch wenn ich jetzt
irgendwie selber ein eigenes Dict, das
Dinge ein bisschen anders macht als ein normales Dict,
äh, verwenden möchte, dann, ähm,
sollte ich halt irgendwie
von User-Dict erben und nicht von, von, von
einfach nur kleingeschriebenem Dict.
Ja.
Dass jeder, wie du das nie, weil sich schon Leute rumgekümmert haben,
bestimmte Probleme zu entgehen, auf die man dann stößt, wenn man das nicht macht.
Ja, ja, genau, genau.
Ähm, ja.
Ja, jetzt haben wir, wir haben noch jede Menge.
Ich weiß gar nicht, ob wir das heute in der Folge alles irgendwie unterkriegen.
Noch ein Anwesender hat gefragt, was denn eine
Shallow-Copy ist.
Achso.
Warum man, äh, wie arbeitet man richtig mit Listen
im Zusammenhang mit Funktionen? Oder gibt man eine Kopie
und retournt eine neue Liste? Oder gibt man eine
Liste und ändert die quasi in Plays?
Was hat das damit zu tun? Also, irgendwie.
Ähm,
ja,
das ist auch eine eher auf unabständige
Zielfrage, was man da machen
möchte.
Äh, also einmal,
äh, vielleicht zuerst das mit der, mit der Shallow,
äh, Kopie, ähm, also die, die
Frage ist, was, was passiert eigentlich, wenn ich
jetzt, äh, sozusagen eine Kopie
von irgendwas machen möchte und, ähm,
äh,
äh, weil ich,
weil ich, äh, warum,
warum auch immer irgendwie eine zweite Version
von irgendeiner Datenstruktur brauche oder so.
Äh, da ist es, wenn ich jetzt, äh,
die einfach nur kopiere, also wenn ich jetzt,
also, in, in Python
habe ich eigentlich immer Referenzen auf, auf solche Datenstrukturen
in der Hand. Also auch
die, äh, Übergabe von Sachen ist
immer bei Referenz, also es gibt ja ein C,
es ist unter Umständen anders, da gibt es halt,
kann ich Argumente übergeben, äh,
als Referenz oder halt als,
ähm, als, als Wert,
ja, also, äh,
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, äh,
jetzt ist es halt so, wenn ich, äh, einfach nur,
äh, bestimmte Operationen
duplizieren mir halt jetzt diese Adresse,
aber nicht den Inhalt dahinter.
Das heißt, wenn ich jetzt, ich mache eine Kopie davon,
ich, naja, muss mal überlegen, in welchen Umständen
ich das hinkriege, ähm,
wenn ich
jetzt,
wenn ich jetzt einfach nur kopie,
äh, vom,
ich weiß nicht, ob Kopie
ein Bild ist, aber wenn ich einfach nur sage,
äh, kopier mir das mal, dann kann es sein, dass es mir nur
die Referenz kopiert wird. Das heißt, mir wird halt
die, äh, 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,
äh, man hätte damit gerechnet, dass ich jetzt
zwei Listen habe, die, äh, im Hauptspeicher
an zwei unterschiedlichen Stellen liegen.
Und eine Shallow Copy
ist halt eine, die nur, die, äh,
sozusagen, also,
bei einer, bei einer Liste könnte ich jetzt
mir sogar vorstellen, dass es oft, wenn ich jetzt nochmal
Liste drumrum schreibe oder so, dass dann tatsächlich
eine Kopie erzeugt wird. Also eine nicht-Shallow
Kopie, aber, äh, wenn ich
jetzt eine komplizierte Datenstruktur habe
in irgendeinem Dikt oder so, wo, äh,
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, ähm,
äh,
sozusagen... Warum brauche ich dann überhaupt eine Shallow Kopie?
Dann könnte ich auch einfach auf das normale Dikt zeigen, wenn es
eh nur auf das gleiche Objekt zeigt. Also...
Ja, ja, ja, genau.
Genau.
Wenn ich die Inhalte mitkopieren will, oder,
äh, dann
muss, mache ich, gibt es zum Beispiel, ähm,
äh, eine Funktion
aus dem Copy, ich glaube, das ist Standard, ja, Standardbibliothek,
dann sagt man immer, Form Copy, Import Deep Copy,
und dann sagt man, Deep Copy,
irgendwie komplizierte Dikt, äh,
verschachtelte Datenstruktur,
und die geht dann rekursiv da durch und kopiert
den ganzen Kram da raus in eine andere Datenstruktur.
Und dann habe ich halt das tatsächlich getrennt voneinander.
Aber ansonsten ist das halt, äh,
nicht so einfach, ja, wenn ich da, äh,
Dikt, äh,
drumherum mache, dann kann es zwar auch sein, dass das ein neues
Dikt ist an einer anderen Speicheradresse,
und dass die, äh, dass ich die Keys und Values, äh,
kopiert habe, aber die Values waren halt Referenzen
auf irgendwas, und die Objekte hinter diesen
Referenzen haben sich halt nicht geändert, ne, so, und das
kann halt sehr... Da kann man sich so ein bisschen mit in den Fuß schießen,
wenn man sowas übergibt wie leere Listen
als Standardwert vom Keyword. Ja, ja,
da kann man sich, kann man sich böse in den Fuß schießen mit.
Weil dann, also das ist, glaube ich, ähm,
generell das Problem, also bei so ein paar Sachen, die man
als Keyword setzt, ja, wenn man das irgendwie in eine Funktion hat,
da wird ein Keyword übergeben, das setzt man
einem Default-Wert, indem es zum Beispiel eine leere
Liste hat, oder einen, einen random
initialisierten Wert, oder sowas, ähm,
der wird halt beim ersten Mal dann initialisiert, und da steht
dann halt aber eine 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
äh, 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,
ähm, und dann ist es immer die gleiche,
und dann funktioniert es sogar oft, und dann irgendwann
fällt es einem ganz furchtbar auf den Fuß, und man
weiß nicht genau, ja, also das, da, in solchen
Problemen habe ich auch schon lange rumgedebugt,
bis ich mir dann so, oh nein, das ist immer die gleiche Liste,
oh scheiße, und da, da ist
auch da, äh, Konvention, dass man
das eben eigentlich, dass man nicht in, als
Default-Argument, ähm, in eine, in eine
Funktion reinschreibt, äh, irgendwie
Default
gleich, Klammer auf, Klammer zu,
oder so, hält. Man sagt immer None, 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ßengel, ja, also das ist,
das kann, das kann einen schwer
erwischen. Äh. Ja, bei
Random werden übrigens genau dasselbe, also wenn ihr jetzt irgendwo
so ein Zufallswert generieren lassen wollt, wie
von RandomRandom 1 bis 10 oder sowas,
und dann habt ihr ihn einmal initialisiert, der gibt nicht jedes Mal,
wenn ihr die Funktion aufruft, einen Default-Neuen-Zufallswert
zurück, sondern immer dasselbe. Also das ist,
äh, ja, an der Stelle, nicht
intuitiv, also das fand ich auch sehr komisch, dass
er dann nicht einfach jedes Mal beim Aufrufen das neu initialisiert,
sondern dass er halt dann die Objekte nimmt, die er einmal
schon irgendwo liegen hat, ja.
Ja, äh, also
wie man, also eine Geschichte, wie man,
also List-Comprehension macht immer eine Kopie,
ne, wenn man zum Beispiel erzeugt immer eine neue
Liste, ansonsten,
ja, die Kopie aus dem Hobby-Modul, wenn es kompliziertere
Datenstrukturen sind, dann muss man sich das nicht selber,
so oft ist es ja, ich meine, es ist ja wirklich kompliziert, wenn man
da halt, äh, was, äh,
ja, man muss halt rekursiv durchgehen
und das will man ja vielleicht auch nicht selber schreiben, da gibt's halt
schon ein Ding für, ähm, was man da benutzen
kann. Dann, dann ist es so,
naja, was, was diese unterschiedlichen Stile angeht,
also, ähm,
wenn man sich so ein bisschen anguckt, was in den,
äh, es gibt ja unterschiedliche Arten
zu programmieren, ja, so imperativ,
ich würde auch Python eher, auch wenn,
wenn man auch mit Berechtigung sagen kann, es ist auch irgendwie eine
funktionale Programmiersprache,
ähm, ist es doch eher, die meisten
Leute verwenden es halt irgendwie imperativ
und, ähm,
in, in dem, ja,
Lager sozusagen, Paradigma
der funktionalen Programmiersprachen ist es aber eher so, dass
man halt da, äh, und, und nicht
nur da, das setzt sich auch in anderen Bereichen durch,
in JavaScript sehen wir das in letzter Zeit oft,
äh, auch wenn es um so State-Handling
Geschichten geht, da gibt's dann Redux,
ähm, und so,
äh, ähm,
dass, dass man, wenn man, wenn man jetzt, ähm,
solche, solche Sachen
handelt, äh, versucht immer
nur mit, äh, Datenstrukturen
zu arbeiten, die nicht veränderbar sind,
also die mutable sind
und immer nur Kopien erzeugt, wenn man
irgendwas ändert, also man ändert nichts
in einer bestimmten Datenstruktur, sondern man,
ähm, erzeugt
eine neue Kopie und, ähm,
äh, an der
ändert man dann halt irgendwas, beziehungsweise
man ändert nix, sondern man baut es dann halt
neu. Ähm,
ähm, was halt
diverse, sehr, sehr, äh, sehr, sehr coole
Nebeneffekte hat, unter anderem, dass ich Sachen dann
perfekt parallelisieren kann,
äh, dass ich weiß, dass ich keine
Seiteneffekte habe, dass ich, äh,
super testen kann, äh,
das, das, na, es, ähm,
es hat, es hat eine Menge, und immer wenn,
wenn Leute, die aus so einer funktionalen Ecke kommen,
sehen, was man so in Python imperativ
macht, dass man irgendwie, äh, Attribute
von irgendwelchen Objekten ändert oder halt
irgendwie ein Dikt übergeben bekommt, dass man irgendwie
in, dann ändert, oder, äh,
äh,
äh, also würde man jetzt
in funktionaler, äh, in einer
richtigen, Entschuldigung,
in einer richtigen, funktionalen Programmiersprache würde man nie
irgendwie einen Dikt oder eine Liste
oder sowas in der 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 diesen ganzen schönen Effekt hat,
was, wenn man das nicht tut,
was, würde ich sagen, aber in Python oft so ist,
äh, also man,
man ü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, äh, ist es halt, äh, ja.
Das hat vielleicht irgendwas kaputt gemacht.
Ja. Was auf der anderen Seite
manchmal halt auch cool total viel einfacher macht,
als wenn jetzt in, wenn man es funktional schreibt,
dann, und auch effizienter, weil
also einmal ist es so, man kann halt Dinge
nicht mehr so richtig direkt beeinflussen
und, äh, ist es halt so, man muss halt, wenn man
alles immer kopiert und jetzt man,
weil 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
oder manchmal muss man dann schon sagen so, ja, hier bitte
nicht kopieren, das geht einfach nicht, passt dann nicht mehr
und dann, äh, muss man
halt, äh, Sachen
direkt, äh, in place, äh, ändern
oder so und das ist natürlich immer ein bisschen schmutzig, aber
ja.
Ja, ja.
Dunkle Magie, wieder.
Ja, also hängt davon ab, würde ich sagen,
was man für ein Problem hat und, äh,
also wenn man das nicht kennt, dann sich mal so anzugucken,
wie man mit alten Datenstrukturen einfach
nur Immutable irgendwie hält und immer
Kopien zurück, das ist eigentlich schon diese, die, die, das ist schon sehr schick,
aber. Also, dann kommen wir direkt,
schließ direkt an, was ist denn deine Lieblingsdatenstruktur?
Meine Lieblingsdatenstruktur,
also ich, tatsächlich, ja,
Dict.
Hätte ich jetzt auch gesagt, früher fand ich Dict ein ganz toller Dict, aber
ich auch, also vielleicht müssen wir mal
gerade, ist ja.
Naja, also, und vor allen Dingen ist die, die Dict-Inflamentation
in Python ist halt auch total super.
Also, die ist richtig schnell,
äh, die, die ist, ja, ja, ist halt sehr effizientes
Ding und ein Riesenhaufen
Probleme lassen sich dadurch schon lösen, ja, 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 Dicts
irgendwie abgebildet. Ähm,
Listen braucht man auch, äh, halt gerade,
wenn man irgendwelche Dinge iteriert und so,
aber, äh, Dicts ist halt
das schöne,
das Schlimme daran ist, dass man halt irgendwie sozusagen
beliebige Dinge irgendwie speichern kann, ja, und, äh,
man kann die
Namen, unter denen man das findet,
dann halt irgendwie dynamisch generieren und, äh,
muss das halt nicht vorher definiert haben in Code.
Mhm. Ja.
Und, äh, wann nutzt man denn Tupel,
das Plattenstruktur, wenn man eine Listen hat? Also, warum ist das
überhaupt? Ja, Tupel sind, ähm,
sind halt immutable, ja, genau.
Äh, das ist halt der Grund, deswegen
an den Stellen,
wo man's halt immutable haben will, dann kann man,
kann man die halt gut nehmen.
Zum Beispiel, wenn du halt möchtest, dass etwas
Dict, äh, Key in einem Dict sein kann, ne,
das geht halt mit einer Liste nicht.
Da musst du halt einen Tupel nehmen.
Ähm, oder
halt bei so Geschichten wie Tupel,
Unpacking und so, da, das geht auch nur
mit, äh, doch, das geht auch mit Listen.
Klar, das geht auch mit Listen, aber
ich weiß, ich überlege jetzt gerade, ob es einen tieferen Grund
gibt, warum Argumente
Tupel sind.
Also,
ja,
generell,
also, Dict 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 Tupel statt eine Liste.
Aber tatsächlich ist es so,
es gibt auch, äh, also,
eskalare sozusagen einfache Werte,
irgendwie, also sowas wie eine 5 oder
äh,
String, wobei man's, äh,
äh,
Listen und Dicts ist halt auch so das, dass man in allen
Programmiersprachen irgendwie oder allen, vor allen Dingen
in allen Skriptsprachen irgendwie eingebaut findet, ja,
dass das halt auch in Perl und in PHP und in
JavaScript, die heißen halt
in allen, äh, diesen Programmiersprachen irgendwie
ein bisschen anders, ne, in Perl heißt es halt
Hash und, äh, Array, ja,
in PHP heißt es, äh,
Assoziatives Array, äh,
und, äh,
weiß ich nicht, ähm,
JavaScript heißt es halt Object und, äh,
äh, ich glaub, da heißt es aber dann
auch Array, ja, naja.
Aber, äh,
diese Grunddatentypen hast du halt überall, deswegen
war das halt, das, damit kannst du halt schon eine Menge
machen und Tupple gibt's halt
eigentlich, glaub ich, nur in Python
und anderswo nicht, weil es auch sonst nicht so
häufig reinet wird.
Ähm, ist halt schon eher so ein bisschen Spezialfall.
Ja.
Ja, es gibt auch oft von
den ganzen,
äh,
also was auch mittlerweile, glaub ich, ein integrierter
Datentyp ist, ist halt Z in Python.
Ja. Das ist auch, äh,
eine Datenstruktur, die wir relativ häufig, oder
ich benutze die relativ häufig und
von denen gibt's halt dann auch Immutable-Varianten,
weiß jetzt gar nicht, ob's Immutable-Tickets gibt,
äh, aber zum Beispiel von
Z gibt's halt Frozen-Z, eben auch für solche
Fälle, wie du möchtest, dass das irgendwie, äh,
das Key in Dict ist oder so.
Und, äh, den kannst du halt dann nicht mehr
verändern. Ja.
Vielleicht gibt's auch sowas wie eine Frozen-List, ich weiß nicht genau.
Ja. Aber Frozen-Z
benutze ich tatsächlich ab und zu. Frozen-List ist
Tupple? Ja, könnte sein, genau.
Frozen-List ist Tupple, ja, genau.
Ja, ja.
Ähm, okay. Wann muss man denn
Numpy erase? Ja, immer
dann, wenn man halt, äh,
sozusagen,
äh,
so viele Daten hat, dass es, äh, irgendwie
nervtöten wird ansonsten.
Und, äh, wenn man
jetzt die ganzen Spezialfunktionen vielleicht verwenden
will, die halt auch in Numpy und so mit drin sind,
äh, ja,
und, ähm, genau, dann gehen halt die Sachen,
die sonst lange dauern, halt einfach
schnell und sind, muss halt ein bisschen
anders programmieren, äh, ist halt dann
alles drauf ausgelegt, dass das, äh,
vektorisiert wird und, ähm,
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 Numpy erase,
muss man dann mit Lambda's arbeiten oder, äh,
ja, oder halt die Funktionen verwenden, die es schon
gibt. Das meiste gibt's ja, sozusagen, würde ich mal
sagen. Und dann ansonsten, wenn's das halt nicht gibt, dann
genau, übergibt man halt eine Funktion.
Ah. Okay.
Wie sehr realisiert siehst du denn denn Daten für
Übertragungen? Hm.
Ja.
Ähm.
Kommt drauf an.
Also, erstmal, was das überhaupt realisieren ist, halt,
in Zeichenkette umwandeln, dass man das irgendwo hinschicken kann
und dass, wenn man dann weiß, was dahintersteckt,
dann man daraus wieder Objekte baut, mit denen man
Dinge tut. Ja, äh, oder, genau,
ich würde sagen, man hat eine Datenstruktur und man möchte
sie halt in irgendeine Form
so, äh, verwandeln, dass man
sie halt irgendwie über Netzwerke verschicken kann oder
irgendwo hinspeichern kann und man setzt sie hinterher
irgendwo wieder. Aufschreiben kann auf Papier, dann kann man sie abschreiben.
Genau, abschreiben. Und, äh,
hat die gleiche Datenstruktur wieder.
Äh, irgendwie. Äh, und das
kann man natürlich,
nachdem, wie kompliziert das ist, was man halt, äh,
ein- und auspacken
möchte, beliebig kompliziert gestalten.
Ähm,
also das, was heutzutage ganz oft
verwendet wird und insofern ist auch
keine so schlechte Wahl. Jason wird
halt oft benutzt.
Kannst halt dann einfach uns auch, ja,
einfach nach Jason verwandeln.
Also alles, was irgendwie so Richtung Dict ist oder verschachtelt
Dicts und, also was,
wie meistens hast du irgendwie
Listen und Dicts irgendwie ineinander verschachtelt,
sozusagen als Datenstruktur. Und das kannst du halt hervorragend
irgendwie als,
als Jason einfach. Also auch mit
kein Problem, auch mit Tucheln kein Problem.
Ähm, Daten, also
Datums. Genau, das ist
Datumsformate, das ist halt
blöd. Genau, solche Sachen gehen dann schon nicht mehr
so gut, ne? Also, wenn du jetzt ein
Datum hast, dass du irgendwie, oder ein Zeitstemp,
äh, irgendwie einen Zeitpunkt, wenn du den irgendwie
in Jason, äh, speichern
willst, dann ist halt blöd. Also der, der
Vorgang von Datum ist Daten, ne? Das ist aber gerade
ein bisschen verwirrend, wenn wir über Daten schon so reden.
Aber ja. Ja, genau.
Das ist, das ist ein bisschen kacke.
Ähm, und dann gibt's 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
Spring, der da in dem Jason
steht, ähm, was das denn, was
in der Limit jetzt gemeint ist. Und das ist manchmal ein bisschen,
bisschen nervtötend.
Ähm, aber, äh,
solange man nicht, also Datum ist immer etwas, was
meistens dann Probleme macht. Aber einfach
so Listen, äh,
Dicts, äh, Strings,
das funktioniert ganz gut.
Und, ähm,
ja, also für diese einfachen Fälle
ist Jason ganz gut geeignet.
Äh, da da auch mittlerweile
so viel verwendet wird, ist da auch viel Arbeit reingeflossen,
wie Parser und, äh,
ähm, äh,
Rausschreibdinger halt so schnell
zu machen. Und das geht eigentlich alles ziemlich gut.
Ähm, es ist halt auch
halbwegs, äh, sparsam, was halt
sozusagen den Platz angeht.
Eben sowas wie XML nimmst. XML ist halt da,
äh, kannst du mehr mitmachen. Aber
es ist halt komplizierter. Es sind auch, und viele Dinge
sind da schon gedacht worden. Aber, äh,
das ist halt einfach, es ist, es wird
oft riesig.
Was heißt 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, äh, auch definieren, wie
die Daten aussehen. Du kannst beschreiben,
wie das, was du,
sagen wir, reinschreibst, wann das okay ist.
Du kannst halt eine DTD, äh,
Data, wie heißt das, Data Type Definition,
zu deinem XML
dazuschreiben. Das halt sozusagen definiert, wie
das Format von deinem XML aussieht.
Und dann kannst du das validieren dagegen und so.
Ja.
Wow.
Aber, äh.
Ein heimlicher XML-Fan?
Nein, nein, nein, nein, nein.
Los, nicht.
Nee, das ist alles sehr schrecklich. Also, äh,
ich meine, man kann das machen, aber das ist alles, äh,
nee, das, es gibt auch einen Grund, warum das
quasi niemand, also,
niemand tut.
Äh, das ist,
oh, ja, also,
in der Anfangszeit war das, äh,
oder ich, also, mittlerweile ist das
auch alles nicht mehr so schlimm, das gibt gute Bibliotheken,
aber, äh,
äh, es war schon, war schon nicht
so einfach, äh, manchmal. Und was halt an XML
nervtötend ist, ist halt, du kannst es als Mensch nicht gut lesen,
es ist halt gigantisch groß,
ähm. Hässlich.
Hässlich, ja. Ähm.
Ähm.
Ja, äh,
und, äh, dann gibt's natürlich noch sowas wie Jammel
oder so, heute irgendwie so ein bisschen auch
wieder en vogue, äh.
Auch hässlich. Ist aber auch, ja,
ist auch ein bisschen hässlich, muss man leider sagen, ja.
Äh, also, wie hat das
mal jemand, äh, von mir, ne, so irgendwie
Jammel, das, also, das raus, das, was dabei rauskommt,
wenn man irgendwie alle Fehler
ignoriert, die bei, bei Jason gemacht worden sind.
Und Jason ist das, was rauskommt, wenn man alle Fehler ignoriert,
die bei XML gemacht worden sind.
Und die, äh,
Geschichte wiederholt sich immer und immer wieder.
Irgendwie das nächste Format heißt, was man nicht gebrauchen kann.
Genau, das ist halt echt so ein, aber
XML ist auch so ein bisschen, äh, das
wurde früher immer gespottet, ne, dass man
dem Format ansieht, dass es irgendwie von Juristen
und nicht von Informatikern konzipiert wurde.
Und dass man irgendwie solche Sachen nicht hat, wie,
also, äh, du kannst es nicht ordentlich quoten.
Äh, wenn du jetzt zum Beispiel,
du kannst halt innerhalb von XML,
gibt's halt sowas wie Kommentare,
wie willst du XML-Kommentare quoten? Das geht überhaupt gar nicht.
Und das heißt, wenn du jetzt zum Beispiel, äh,
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,
das geht einfach nicht. Und, ähm, ja,
es ist alles,
es ist nicht so, dass man sich sagt, das ist voll super elegant,
total gut, äh, nehmen wir jetzt sofort.
Sondern es ist mehr so, oh, schrecklich.
Ähm, und JSON ist
aus dieser Perspektive für mich weniger schrecklich.
Also, es ist halt, es kann deutlich weniger.
Aber, äh, okay, äh,
dafür ist es halt alles nicht so schlimm.
Ist ja zum Serialisieren da, also, dass man Daten irgendwo hinlegt,
als, ja, Pfeil oder sowas.
Aber es gibt natürlich dann gewisse Begrenzungen,
so was halt dann nicht gut funktioniert.
Äh, eben, ja, Datum oder alles,
was irgendwie komplizierter Objekte sind und Code,
kannst du da auch nicht mit reinpacken.
Das geht alles nicht.
Und, äh, auch dann für die Übertragung im Netz
ist es halt auch teilweise nicht so gut,
weil das halt dann Text ist und, äh,
das hat 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, kann man halt,
ist so ähnlich wie JSON, bloß, äh,
binär, äh, so, dass das halt, äh,
irgendwie nicht kaputt gehen kann
bei der Übertragung oder nicht so leicht kaputt gehen kann
wie JSON.
Ja, ähm,
und, naja, aber,
aber JSON ist eigentlich schon, würde ich sagen,
für viele Fälle so das, was man eigentlich haben will.
Und, ähm, wenn es dann noch viel
komplizierter wird, kann man auch sowas nehmen wie Pickle,
da muss man aufpassen, ähm,
ja, es gibt noch in, in, in Python, äh,
in Python selber, wenn ich jetzt überlege,
gibt es noch, äh, eingebaute Geschichten, es gibt noch Marshall,
das Modul, das macht sowas ähnliches wie
JSON, bloß halt, äh, binär.
Das ist auch noch ein Stückchen schneller.
Und dann gibt es noch Shelf, glaube ich,
das weiß ich aber nicht, hab's auch schon ganz lange nicht mehr verwendet.
Ähm, und
eben, wenn man jetzt aber nicht nur,
äh, Daten, äh, äh,
serialisieren will, sondern vielleicht auch Code mit,
also komplette Objekte mit Funktionalität,
dann, äh,
ja, sowas wie Pickle.
Und Pickle kann man auch schicken als Binär-File, dann einfach übers Netz,
und dann kommt... Genau, man kann das in, äh,
man verwandelt halt ein komplettes Objekt zum Beispiel in einen
binären String,
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,
man muss halt sehr aufpassen, äh,
äh, dass man dann führt der Code aus, ja,
also wenn, äh,
wenn einem jemand irgendwie, äh,
der nicht vertrauenswürdig ist,
irgendwie irgendwas Gepickeltes schickt,
da kann beliebiger, kann beliebiger Code drin sein,
ja, also wenn man das anpickelt,
dann führt man das aus, was da drin steht.
Das heißt, äh, ja, das sollte,
das sollte man sich klar machen,
dass das... Hier ist eine Bombe.
Genau, dass man, also,
ja, irgendwas, äh,
anpickeln, was einem jemand gibt,
ist so wie irgendwie Code ausführen, der einem jemand gibt,
also das ist halt... Wenn ich ein Paket öffne, was man nach Hause
geschenkt bekommen hat, der kann auch,
ja, Briefbombe drin sein, man weiß es nie so genau.
Das ist immer auch beim Essen, wenn man isst,
was man nicht kennt, dann immer Vorkost da dann.
Ja.
Man weiß es nie so genau, also, ne,
die Paranoia kann ja beliebig weit getrieben werden.
Genau, genau, genau. Äh, Pickel,
lass mal überlegen, gibt's noch, es gibt da noch diverse,
es gibt da noch für den wissenschaftlichen Bereich
ein paar Sachen, es gibt noch HDF5,
äh,
äh, wie heißt das Ding, NetCD,
äh, ich hab's jetzt wieder vergessen,
äh,
ähm, wie der Standard ist, also wie,
ja, es gibt so eben für wissenschaftliche Daten,
gibt's noch Standards, wie man,
äh, wie man Sachen speichert,
die noch so ein bisschen anders sind,
äh, NetCDF, glaube ich,
das ist, ja, so, und HDF5
ist einer der, es gehört da irgendwie
mit rein in diese Reihenfolge.
Ja, das hört sich irgendwie total kapiert an.
Äh, ja, ähm, und, ähm,
NumPy-Arrays haben auch nochmal eine eigene Möglichkeit,
wie man sie serialisieren kann,
man kann ja auch Memory mappen, äh,
ähm,
ja, oder, ich mein, 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, äh,
also, äh,
in anderer Sicht ist es auch wieder ganz gut, also,
oft, äh, würde ich sagen, dass, äh,
wenn man die Wahl hat zwischen CSV und XML,
ist CSV die bessere Wahl,
aber, äh, ja,
ähm,
tja, ja, aber das,
das war's im Grunde eigentlich,
ja, haben wir noch irgendeine wichtige Serialisierungsgeschichte?
Ja, ich glaube, also, wir wollen ja jetzt auch,
eigentlich wollen wir ja nur eine Minute reden, ich glaube,
dann halten wir uns jetzt voll.
Ui, ui, ui, ui.
Ja, ich hab jetzt noch so ein paar Themen, die sind irgendwie jetzt alle aber sehr unzusammenhängend,
auch, ähm, 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, da haben wir ja über den JIT und den GIL gesprochen,
an den, äh, Just-in-Time-Compiler
und den Global Interpreter-Log,
ähm, dann, äh, hab ich jetzt noch stehen,
äh, das Konzept von MapReduce, aber ich weiß nicht,
ob das jetzt hier zugehört, dass das irgendwie nicht ganz
da reinpasst. Nee, ich glaube auch, es ist auch so ein bisschen veraltet,
also, dass man zwischendurch macht das keiner mehr.
Und dann, äh, was mich aber natürlich noch interessiert,
wenn man halt debuggen möchte, was da irgendwie
der Zeug ist, dann gibt's da irgendwie so ein bisschen
so, ich nenn's jetzt mal Deep-Debugging,
das heißt, man kann, äh, Deer auf irgendwelche
Feele spawnen oder Help aufrufen
und so, was gibt's denn da noch und wie würde man
sich dann angucken, was überhaupt möglich ist
mit so Objekten, die man da, äh, zurückbekommt,
wo man nicht genau weiß, woran liegt denn das jetzt,
guckt man denn da genauer rein?
Naja, ich glaub, das ist schon, äh, also, Help zeigt halt den...
Also, macht man Help, das sind Funktionen, die
man außen rumschmeißt und was, was zurückkommt, oder?
Mhm, äh, ja, aber das, äh,
also, an den Objekten hängen halt auch
immer Dinge dran, also, zum Beispiel, man an dem
Funktionsobjekt hängt halt auch immer die Dokumentation,
also, der Dockstring hängt da halt mit dran, den man sich dann
angucken kann und ich weiß nicht genau, was Help macht,
aber Help, glaub ich, wird sowas tun, wie
die Dockstrings nehmen und anzeigen,
mehr oder weniger, ähm,
und, äh, Deer zeigt halt
alle Attribute und, äh, Methoden
oder so an einem Objekt,
die da so dranhängen, äh,
und
dann, äh, ja,
also, zumindest, äh, kann man sich dann,
zeigt das auch die Funktion Signature, glaub ich, an,
noch... Was gibt's denn noch?
Äh, ich glaub, ne, mehr, mehr verwende ich
eigentlich auch, äh, praktisch nicht.
Das ist dieses MRO, ne,
dieses Basis, also, wenn man so eine von diesen
Objekten, die man mit Deer dann rausbekommt, hat, sich's anguckt,
dann bekommt man natürlich noch viel mehr Informationen,
weil diese ganzen, ähm, Magic Methods
und Meta-Attribute irgendwie von den Klassen dranhängen,
dass man, zum Beispiel jetzt, ne, mit Basis
sehen kann, welche, äh, Oberklassen
hat denn überhaupt das Ding, wo ich dann drin bin, so,
und so. Ah, okay.
Cool. Nee, hab ich noch nie verwendet, glaub ich.
Da kann man halt so ein bisschen tiefer reingucken in dieses, äh,
Vererbungshierarchie-Ding und, ähm, dieses, äh,
MRO, also diese Method Resolution Order,
zeigt dann vielleicht genau, welches von den, äh,
Dingen, die dann aufgerufen worden ist,
aufgerufen worden ist, von den Methoden, die man jetzt
in reiner Weise überschrieben hat, und was da eigentlich
hinter steckt, damit man vielleicht weiß, oh, es wurde etwas
Falsches aufgerufen, also so kann man so...
mal gucken, wenn irgendwas schief geht, wo man überhaupt nicht
weiß, was man da gemacht hat, dass man nicht irgendeinen
Komma gegessen hat, 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 empfehlen?
PDB ist halt so das, was man kann ja auch inzwischen...
Was macht PDB? Also der stoppt den Code
zur Ausführzeit, man hat eine Shell und kann
dann da hochgehen.
Man kann es halt auch irgendwie
im Code halt rein
set trace,
schreibst halt einfach
deinen Code rein und dann hast du da halt
einen... Stoppt halt
die Ausführungen an der Stelle und 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 gucke dann wieder, was ist denn da los.
Genau.
Und dann weißt du ja genau, wo du bist.
Also das ist eine schöne Geschichte.
Ich weiß jetzt nicht, seit wann
das Tracing eingebaut ist.
Das 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
entsprechend schnell.
Ich glaube, das gehört auch mit der VS Code.
Also der Editor hat das irgendwie auch implementiert.
Ja, das muss ich auch nochmal angucken.
Gar nicht richtig benutzt.
Man kann halt dann so Debug-Stops setzen und so.
Ja, Breakpoints.
Introspection, ja genau.
Ja, ich habe jetzt noch zwei andere wieder.
Punkt drauf, die nichts mehr da 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
halt 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.
Weil,
nicht gleichzeitig, weil
Sachen auf einer CPU natürlich doch dann
irgendwie mal sequenziell abgearbeitet werden.
Aber,
ja,
man benutzt die 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 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.
Völlig okay.
Also Async.io macht dann echt das Multithreading
auf Multiprozessoren?
Nee, das macht kein Threading. Async.io ist wieder eine andere Geschichte.
Was ist das?
Async.io ist, ja,
kann man sagen, einmal ein 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.
ja,
das,
ja, aber das müssten wir, wenn man das wirklich erklären
würde, das funktioniert, müssen wir nochmal eine Folge dazu machen,
das,
eben, damit kann man halt auch IOMultiplexen
und das Ganze
in einer etwas intuitiveren Art
hinschreiben, als wenn man das jetzt mit Threading
machen würde. 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,
also,
wenn man da Tracebacks kriegt irgendwo in
Workern, die halt in unterschiedlichen
Threads laufen, das kann sehr,
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 ist 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 Async, also
so ist das halt in den Stellen, wo
man auf ein Syscall wartet oder so, wo es blockiert,
da macht
man 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 Async.io wahrscheinlich
die interessantere Geschichte, die man sich angucken
sollte, weil es mehr
aussieht wie ein normales Programm.
Aber Threading kann man
durchaus auch machen. Und es ist wahrscheinlich
sogar ein bisschen schneller, wenn man wenig Threads hat.
Aber, ach, das ist eigentlich
auch furchtbar, das spielt alles keine große Rolle.
Okay. Ja,
dann was ist Covered?
Oh, wuh!
Ganz interessant.
Ja, meinst du das
Paket oder das Modul? Achso, die Coverage.
Ja, sozusagen, wie viel
ähm,
ja, 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 im Teil ganz gut,
gibt es 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 das ist 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 wird dann, manche Sachen sind einfach schwer zu testen und
irgendwann
wird es halt dann sehr aufwendig
und, also die erst
80% so stabil, wie das so immer ist,
die gehen relativ einfach und dann die letzten 20%
brauchen dann nochmal
80% der Zeit irgendwie,
weil das dann 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
Funktionen einzeln testen zu können.
Und, ja,
oder manchmal macht es dann
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 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,
so hat man aber auch wirklich alle,
gibt es viele unterschiedliche,
also 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 nicht mehr nicht so ganz klar,
was gemeint ist, wenn man jetzt Coverage sagt.
Und, ja,
das kann man dann auch nochmal,
also 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 man auch bei Coverage noch einstellen.
Etwas feiner.
Aber, ja, genau.
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 dem Test.
Ja, dann haben wir
fast ja schon die letzte Frage. Ich glaube, wir sind da schon
lange wieder heute dabei.
Und zwar auch wieder eine
höhere Frage. Wie man die Performance,
die Speichernutzung der Codes prüfen
und vergleichen kann.
Ja, also
was ich oft mache,
ist tatsächlich, aber ich meine,
ist ja 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...
Wie viel Speicher noch frei ist.
Ja, und wie viel Speicher
verbraucht ein Prozess. Und wenn
dann halt irgendwas läuft, dann weiß ich
ungefähr, wie viel Speicher das verbrauchen sollte.
Und wenn das doppelt oder dreimal so viel verbraucht,
dann weiß ich,
wenn ich da 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.
Genau.
Das kann aber mit Memory-Geschichten nicht so viel machen.
Für Memory-Geschichten,
für Memory-Sachen, glaube ich,
nimmt man dann eher so ein bisschen K-Cache-Grind oder sowas.
Aber das ist...
Aber wenn man das jetzt im Jupyter-Notebook machen möchte,
weil man jetzt keinen Pop hat oder sowas...
Naja, du kannst dir halt
von den Datenstrukturen anzeigen lassen,
wie viel Speicher sie verbrauchen.
Da habe ich jetzt auch wieder vergessen,
du kannst in einem
Panas-Data-Frame sagen, irgendwie
meminfo 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 viel 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 steckt so viel Speicher drin.
Dein ganzes
Jupyter-Notebook, also du kannst dir deine
einzelnen Datenstrukturen angucken.
Bei NumPy-Arrays ist es halt viel einfacher noch.
Ich glaube, da gibt es auch eine Funktion, die einem sagt,
welche Hauptspeicher irgendwie ein Array
verwendet, aber da ist es ja einfach,
du kannst dir den D-Type angucken von dem Ding,
und du kannst dir auch angucken mit Shape, wie viel da drin liegt,
und dann multiplizierst du das einfach mit,
wie viel Bit hat halt hier
irgendwie der Typ, den ich da verwende, mal Anzahl
Einträge, und dann weißt du, wie groß das ist, weil da ist es halt
sehr einfach.
Also so kann man bei einzelnen Sachen rausfinden, wie viel
Hauptspeicher die verbrauchen, weil das, wie viel das
Jupyter-Notebook insgesamt verbraucht, siehst du halt
im Top.
Der Speed?
Ja, da brauchst du wahrscheinlich auch,
kannst du natürlich auch global
das bestimmen,
indem du halt, also auf der Shell schreibe ich
auf Time einfach davor, und dann
kriege ich halt dann eine Ausgabe, wie viel
wie lange das 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 da möchte man das halt ein paar Mal
ausführen, sodass halt dann auch so
Cache-Effekte und so nicht so eine Rolle spielen.
Und da gibt es dann halt
auch Prozent-Time-Magie,
wo das dann halt 10.000 Mal ausgeführt wird,
und dann wird dann halt Durchschnitt berechnet,
und dann ist es okay, diese Funktion dauert irgendwie
üblicherweise,
1,7 Nanosekunden,
1,7 Nanosekunden wäre schnell für die Funktion.
Und dann weiß man halt,
okay, wenn ich die jetzt so oft aufrufe,
dann dauert das halt.
Ja.
Genau.
Und ansonsten eben C-Profile
kann man verwenden, wenn man es genau
möchte, wenn man jetzt noch gar keine Ahnung hat, wo 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
halt so ein Profile eine ganz hilfreiche
Geschichte, und dann, wenn man weiß, wo man
Zeit verbringt, dann kann man halt mit
TimeIt zum Beispiel in der Notebook-Zelle
halt dann irgendwie gucken, ob man das irgendwie optimiert
kriegt, und dann kann man sozusagen 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.
Ich hoffe, das fandet ihr wieder interessant.
Genau.
Ja, genau, haben wir noch irgendwie
Pics oder sowas? Pic der Woche?
Ja.
Bis Monats!
Ja.
Also, ich hätte
da noch was. Ja, was ist dein Pic
der Monats?
Und zwar,
ich habe mich
letztens wieder damit beschäftigt,
mich nochmal aufzusetzen,
und habe dann
nochmal so irgendwie angeguckt, ob es nicht
wie macht man das eigentlich vernünftige
Python-Entwicklungsumgebung
aufsetzen. Dazu gab es einen
Artikel
von Jacob Kaplan-Moss, glaube ich,
einer der
Django-Gründer
da,
hat dazu irgendwie meine
Python-Entwicklungsumgebung 2020
Edition oder so einen Artikel geschrieben,
das sollte ich mal verlinken, und da dachte ich so, ah, gut,
dann gucke ich doch mal, was der so macht, dann
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, mir haben Leute davon erzählt,
aber habe es irgendwie nicht benutzt, ist PyEnv.
Und das war so eine der Geschichten, die ich,
also, genau, das wäre halt beim Tick, PyEnv,
und das ist eigentlich
ziemlich cool, weil
das ist halt ein kleines
Tool, was einem
dabei hilft, halt Python zu installieren, was
überraschend schwer ist, es sollte eigentlich nicht so schwer sein, aber es ist halt
ein ganz schönes Adson,
vor allen Dingen braucht man Python oft
in sehr unterschiedlichen Versionen,
unterschiedlichen Arten, wie man es
installiert, so, für manche Projekte brauche
ich halt Minikonda
oder Conda, ja, so, und
mache, benutze auch Conda zum
Installieren von irgendwelchen Abhängigkeiten und so,
und Paketen in anderen
Webentwicklungsgeschichten wie der Virtual Envs,
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 so,
was,
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, also
der installiert dann halt auch, PyEnv installiert
halt auch Minikonda und sowas,
und dann kann man halt sagen,
okay, PyEnv install Minikonda
latest, und dann hat man halt die,
muss man nicht mehr sich damit beschäftigen, da
irgendwie dieses Shell-Skript,
irgendwie Curl in irgendwie Shell-Skript
zu pipen, und dann Minikonda
zu installieren, sondern es 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
auch ein Name
von einem Virtual Env sein, dann ist man halt in diesem
Virtual Env, oder
es kann halt der Name sein von einem Conda-Environment,
und das ist halt
sehr, sehr cool, das heißt, ich hatte
vorher sonst immer ein MK,
also Virtual Env-Wrapper verwendet,
und dann immer so Post-Activate-Skripten,
einmal
dann halt,
achso, ne, ich überlege gerade,
ob das nicht ein anderes Thema ist, aber ne,
ins Verzeichnis
gewechselt, dann 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 dann geht einfach
in das Verzeichnis, und dann ist gut.
Also es funktioniert noch nicht alles hundertprozentig,
das ist auch noch so eine Idee. Ich glaube,
ich packe das irgendwo, wo packe ich denn 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 ja auch noch Ideen, was man da an tollen
Dingen machen kann, und vor allem, manche Sachen
funktionieren auch nicht so ganz sauber, also von
irgendwie Virtual Env nach Conda
wechseln, das geht irgendwie, aber umgekehrt geht irgendwie nicht,
oder so, weiß nicht genau, warum.
Ja, und
vielleicht wäre das mal eine sinnvolle Geschichte,
das mal zusammenzutragen, was muss man eigentlich machen,
um halt eine ordentliche Python-Entwicklungsumgebung
irgendwie aufzusetzen.
Ja, das geht auf jeden Fall nach einer guten Sache.
Genau.
Und genau,
fand ich jetzt sehr, sehr
überzeugend eigentlich, und
bin ich eigentlich
dachte ich mir, warum fände ich das jetzt eigentlich
nicht schon immer, sozusagen, weil das
vereinfacht doch eine Menge Sachen deutlich.
Ja, ich habe auch einen
kleinen Pick der Woche, also ich nehme diesmal
Türkel, diese kleine Bibliothek, mit der man
kleine Sachen zeichnen kann auf einer
Kennung. Ach, so eine Grafik, ja. Ja, weil da kann man tatsächlich
ganz lustige Sachen damit machen, zum Beispiel Kunst,
man kann sich Algorithmen in den Mandelbrotmengen
berechnen lassen, Funktionen, und der zeichnet dann ganz
tolle, witzige Bilder, mit denen
man Computerkunst macht.
Also, unabhängig davon, dass man jetzt einen kleinen
Schildkröte über den Bildschirm 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. Egal wann ihr hört,
Montags, Mittags, Abends,
Nachts, bleibt uns gebogen, habt viel Spaß
und wir hören uns bald wieder.
Ja, bis zum nächsten Mal. Tschüss.
Musik
Musik
Musik
Musik
Musik
Musik
Musik
Musik
Musik
Auf Takt
Im Takt
Im Viertakt
Soll es klingen
Drei kleine Dimensionen
So Taktvoll
Lichtspiel
Impressionen
So Farbvoll
Farbton
Halbton
Und Synchron
Dazu schwingen
Drei kleine Dimensionen
So Taktvoll
Lichtspiel
Impressionen
So Farbvoll
Wohlglang
Delusionen
Delusionen
Die Unkontrollen
Von Zwu起
Von Zwu
Von Zwu
Von Zwu
Von Zwu
So taktvoll.
Licht spielt Impressionen.
So farbvoll.
Klänge.
Zu Millionen.
Überwinden.
Die Distanzen.
Dreiklangs Dimensionen.
So taktvoll.
Licht spielt Impressionen.
So farbvoll.
Klänge.
So taktvoll.
Dreiklangs Dimensionen.
So taktvoll.
Ausgang.
Abgang.
Sequenzen.
Ohne Grenzen.
Dreiklangs Dimensionen.
So taktvoll.
Licht spielt Impressionen.
So farbvoll.
Dreiklangs Dimensionen.
So taktvoll.
Licht spielt Impressionen.
Dreiklangs Dimensionen.
So taktvoll.
Licht spielt Impressionen.
So farbvoll.
Dreiklangs Dimensionen.
So taktvoll.
So farbvoll.
Dreiklangs Dimensionen.
So taktvoll.
Licht spielt Impressionen.
So farbvoll.
Dreiklangs Dimensionen.
So taktvoll.
Dreiklangs Dimensionen.
Drei Glanzdimensionen, so taktvoll.
Licht spielt Impressionen, so farbvoll.
Drei Glanzdimensionen, so taktvoll.
Licht spielt Impressionen, so farbvoll.
Drei Glanzdimensionen, so taktvoll.