Transcript: Arrays und Sequenzen
Full episode transcript. Timestamps refer to the audio playback.
Ja, hallo liebe Hörerinnen und Hörer, willkommen beim Peißen-Podcast. Heute Episode 59. Hi Jochen.
Herzlich willkommen Dominik. 59, meine Güte.
Ja, hi Johannes.
Und hallo Johannes.
Wir machen heute weiter mit dem Flunen-Peißen-Buch, haben wir uns gedacht.
Ja, genau. So, hat sich bewährt.
Ja, ich fand das ganz gut.
Bleiben wir jetzt. Machen nur noch das.
Es ist ja auch lang.
Wenn wir hinten angekommen sind, dann machen wir es nochmal rückwärts.
Dann haben wir es schon vergessen, dann müssen wir es von vorne direkt wieder vorlesen.
Ja, wir hatten, also das Kapitel 2 hat was mit Sequenzen und Listen und sowas zu tun, da hatten wir ja schon mal eine Folge, ne, erinnert ihr euch?
Ja, aber da gibt es einfach immer noch mehr zu sagen.
Genau, ich hatte da auch nochmal reingeguckt kurz und wir haben da, also das ist ein bisschen orthogonal, das ist gut, also es ist halt von der anderen Seite nochmal angegangen und da das Thema sowieso irgendwie wichtig ist, dann kann man das auch von mehreren Seiten mal irgendwie angehen, das ist eigentlich ganz gut.
Okay.
Ja.
Haben wir denn News?
Ja, so ein bisschen, ich habe jetzt, ja, ist halt die Frage, was da alles so drunter fällt, Python 3.13, das machen wir jetzt nicht, aber das kommt jetzt ganz bald.
Ja, also ich finde ja den REPL so schön.
Ja, genau, habt ihr euch alle schon so ein bisschen damit beschäftigt oder gar nicht?
Nee, gar nicht.
Auch gar nicht?
So ein ganz kleines bisschen.
Ja, also genau, also ja.
Der REPL ist total toll, du kannst einfach Defaults jetzt eintragen, den er automatisch lädt, Pakete in deinem REPL.
Das heißt, wenn du den Interpreter aufmachst, dann hat der
Pakete schon geladen. Oder damit
kannst du halt auch Sachen dann überschreiben, weil er dann die Pakete
lädt, die er laden soll. Und du hast
einen Befehlssatz drin direkt, den du möchtest.
Also eine eigene Konfiguration für deinen
Ripple direkt haben.
Man kann einfach Exit eingeben und ist draußen und Multiline
Editing und die History ist ordentlich
und so. Das finde ich jetzt alles nicht so
beeindruckend, weil ich habe eh immer
einen IPython überall.
Ja, aber rate mal, wer das nicht hat.
Der Dominik.
Nee, die Python-Ur-Entwickler.
Deswegen alle
mit allen neuen...
Die schauen dann mit Neid, schauen die so...
Ja, aber iPad ist so cool.
Oder Beep-Python.
Genau, und das geht alles nicht, weil das läuft ja mit der neuen
und in der Entwicklung befindlichen
Python-Version funktioniert das halt nicht.
Das heißt, die müssen immer die Python-Rapid verwenden und die
sagen alle,
das ist so viel besser jetzt, das ist so cool.
Ja.
Ja, das ist typischer
Software-Entwicklungsmechanismus.
oder Softwareentwicklung durch Neid.
Ja. Ja, erstmal bitte ein bisschen
Rennbogenfarben irgendwie in der Konsole,
dann macht das Spaß. Ja.
Und ein großer Teil davon kommt halt auch,
oder kam, also Anregungen dafür
kamen aus PyPy.
Und dann haben sie es jetzt aber nochmal durch die Mangel
gedreht und alle möglichen Sachen gefunden, die man irgendwie
besser machen soll. Jetzt überlegen sie, ob der Kram,
den sie in Seapython jetzt gemacht haben, nicht zurückgeht nach
PyPy wieder.
Aber das ist cool. Also das ist
auf jeden Fall, das sind einige
Sachen, die jetzt auch da immer wieder
zwischen den Leuten dann diskutiert werden und so.
Und da ist auf jeden Fall eine fruchtbare Diskussion
immer so im Stande. Ich höre ja diesen
Copy-By-Podcast und da ist eigentlich
PiPi immer mit dabei oder
ja,
Karl Friedrich
bei Band als
irgendwas, das hat er dazu gesagt.
Ja, also das ist auf jeden Fall cool.
Genau, Python 3.3,
die Repel-Geschichten.
Ja, es gibt halt, also das größte,
das dickste Feature, was immer alle
nennen, ist halt
Free Threading, also
man kann den GIL
abschalten.
Ja, also... Das sind schon, das würde ich
schon sagen, das sind schon nennenswerte News.
Ja, ja, schon, schon, klar, und also
in gewissen Fällen bringt das sicherlich
auch viel, aber... Die auch vielleicht eine eigene
Episode brauchen. Ja, genau, da müsste man auch mal
äh... No-Gay.
Genau.
Ja, das ist halt auch mit drin. Hashtag, Hashtag No-Gay.
Ja, überhaupt
dieser ganze, der, äh,
Es gibt
einen Just-in-Time-Compiler, der jetzt mit dabei ist.
Der macht zwar noch nicht viel, aber er ist auf jeden Fall
jetzt drin. Das heißt, da könnte
man in Zukunft auch irgendwie einige
coole Performance-Verbesserungen
erwarten. So ein
Copy-and-Patch-Jit
ist jetzt tatsächlich
in Python-Interpreter mit drin.
Ja,
was haben wir noch alles?
Genau,
es gibt jetzt farbige Phrase-Bags.
auch wieder so ein, ja,
für den Alltag irgendwie ein bisschen besser.
Ja gut, das sind natürlich schon alles.
Also er hat auch immer einen guten Hint, er
racet jetzt nicht einfach irgendwas und denkt sich so, oh ja,
komisches Straightback, so weiß ich nicht wo,
sondern er hat oft schon eine gute Intuition, was das
sein könnte. Ja, genau.
Da ist jetzt auch eine...
Also da sind jetzt Dinge
verschieden große Signifikanz
dabei, würde ich sagen. Ja.
Ja, aber tatsächlich für Anfänger,
also was die oft irgendwie,
ein Problem, das sie hatten, ist,
du nennst
dein Python-Modul
oder Skript, das du gerade schreibst,
nennst du halt genauso wie ein Standard-Lib-Modul
und
wenn das Versuch auszuprobiert
passiert, kriegst du eine total
kryptische Fehlermeldung, die dir echt gar nicht
weiterhilft. Und
da gibt es jetzt eine Fehlermeldung, die sagt,
kann es sein, dass du das genannt hast wie ein Standard-Library-Modul?
Das ist aber nicht gut. Mach das mal anders.
Und das ist natürlich hilfreicher irgendwie.
Ja, das ist tatsächlich was, was in
Python-Kursen oft vorkommt, weil man halt irgendwie
haben naheliegende Namen und wenn du
deine Funktionalität schreibst, die
sich mit einem Thema beschäftigt, dann wählst du
den naheliegenden Namen für deine
Python-Partei und schon hast du das Modul
überschrieben. Deshalb, das ist
schon gut, aber ich würde sagen,
es ist, sagen wir mal, technologisch
weniger fortschrittlich
oder weniger kompliziert
als Hashtag NoGill.
Ja, das ist richtig. Da ist eine ganze Menge
Enttäuschung und Aufwand drin gewesen, glaube ich.
Ja.
Ja, ansonsten, genau.
Ich weiß gar nicht, ich habe noch irgendwas zu lesen.
Wir machen zu 3.13 auf jeden Fall
auch noch eine Episode, denke ich, dann können wir das mal
alles zusammentragen.
Ja, ansonsten,
was war noch?
Django 5.1 gibt es auch
irgendwie jetzt.
Ja, aber ändert sich da irgendwas?
Da war auch nichts,
was ich mir jetzt so spontan in Erinnerung geblieben wäre.
Ja, also diese Django-Releases,
da gibt es ja sehr viele immer.
Und ich habe das Gefühl, also klar,
die machen Sicherheit, die machen so Verbesserungen
und dann machen sie schon immer mal wieder
coole Sachen, da mit
diesem Postgres-JSON ändern sich ja schon schöne
Dinge, aber
so richtig...
Oh, wir haben da schon drüber gesprochen, glaube ich.
Wir haben schon drüber gesprochen, diese Query-String-Geschichten
und so, brauchen wir nicht nochmal. Ja, ich hätte, ich habe mir
die Videos nicht aufgeschrieben, aber ich...
Ja, aber ich meine, Django
fühlt sich an, als ob es so stabil ist, dass es
sehr inkrementelle Verbesserungen sind.
Ja, ja.
Das ist ja auch was Gutes, würde ich auch sagen.
darauf verlassen kann, dass das halt, was man
jetzt weiß, wie es funktioniert, dass es auch so bleibt.
Ja, aber
ich hätte noch eine Überleitung zu einer ganz
interessanten Frage vielleicht, wenn wir jetzt hier
schon eigentlich mit den News mehr oder weniger am Ende sind. Also ich weiß
nicht, ob ihr noch was habt. Ich hätte jetzt nur noch irgendwie, es gibt
neue LLM-Modelle, sowas wie
O1 oder... Kann man jedes
Mal als News sagen. Genau, also es gibt
neue, probiert es mal wieder aus. Es gibt
ein 700 Milliarden Parameter-Modell
von Lama.
Lama 3.1 700B.
Ja.
Das, ja.
Brauchst den größeren Rechner.
Also O1-Preview ist ja aber trotzdem auch noch new.
Und das ist, also
ich höre, das ist besser als Cloud wieder.
Ja, also bisher, also genau,
ich würde sagen, also diese ganze
Artefaktsnummer,
ich habe jetzt in letzter Zeit häufig
Cloud, also
das Chat-Interface von
Anthropic
verwendet, weil das halt einfach für Code-Geschichten
oft ein bisschen besser war als
als
GPT-4O.
Und
ja,
aber jetzt inzwischen, also ich weiß nicht genau,
ich habe es noch nicht wirklich ausprobiert, ehrlich gesagt,
weil es ja auch gerade erst rausgekommen ist, aber
das soll halt sich dann auch noch mal wieder
ein bisschen
besser drüber sein.
Also ich finde es jetzt schon super alles.
Also das ist auch, das ganz normale
GPT-4O und so war auch schon super
und die Anthropic-Dinger fand ich auch total klasse.
Also ich bin eigentlich sehr zufrieden.
Es ist ein gutes Zeichen, wenn
einen Chief Machine Learning Engineer
Mensch Anthropic nicht kennt?
Das wäre ein schlechtes Zeichen, würde ich
meinen. Ja, wie kann das denn sein?
Also gut, Machine Learning ist halt ein großes
Feld.
Ja, du kannst dich auch in irgendwas
spezialisieren oder in einem ganz anderen Feld irgendwas
machen, mit LLMs nie irgendwas zu tun haben.
Aber ja, gut.
Ja, also es war schon gut.
Also die großen Namen musst du ja schon
wissen, oder?
Ja, gut.
Aber ja, jetzt haben wir
jetzt gerade eben hier mit dem die Karriere versaut.
War eigentlich eine gute Alternative, ich bin gespannt.
Also O1, ich finde es echt very nice.
Hilft, also es ist so ein bisschen
fehlerfreier
bei Coding-Ding
und so ein bisschen deeperes
Knowledge und es macht sehr viel Spaß, diesen
Gedankengang zuzugucken.
Und das, was ja auch neu ist,
das ist aber schon bei 4.0 drin,
ist halt, dass du ein Gedächtnis hast
jetzt auch. Ja,
was sie da so nennen.
Doch, doch, das ist schon, das funktioniert auch.
man muss sich halt überlegen, ob man möchte,
da hast du es gespeichert, was man da bespricht.
Bitte merkt ihr alles, was ich hier gesagt habe.
Ja.
Aber vor allen Dingen ist das gar nicht so schlecht, weil, also,
ja,
interesting. Ja, ich meine,
also, wenn man jetzt LLMs über die
Kommandorenzahler mit dem LLM-Tool zum Beispiel
benutzt, dann hat man das ja auch irgendwie,
man ist ja lokal in der SQLite, ich weiß nicht,
ja, ist auch immer die Frage, wie möchte man
dieses hier eigentlich zeigen?
Ja, also, ich frage tatsächlich so nach
nach so Morgenroutinen oder sowas und sagt dann halt so, hey,
was ich denn so mache und dann schlägt das Ding mir halt so Dinge
vor, als dass es so, äh, macht mit mir
so Rituale und so. Ich find's sehr lustig und das
funktioniert toll. Und, ähm, das
ist, glaub ich, gar nicht so blöd.
Weil's einen so dabei hält, sich so selber
zu entwickeln.
Ja, cool. Das kann man natürlich auch mit anderen Quellen
machen, dass nicht, dass man jetzt irgendwie so ein
Eifer bräuchte, aber es geht damit sogar
relativ gut.
Ja, genau. Ansonsten würd ich nämlich Django
irgendwie mal kurz zu der Überleitung nutzen,
da wir jetzt sowieso nicht so viel News haben.
ich habe, und
ich mache gerade ein neues Projekt, weil
irgendwie ich prokrastiniere so gerade die Dinge, die ich eigentlich
machen sollte und, naja,
wer kennt das nicht?
Ja, sinnvolles Prokrastinieren.
Produktives.
Genau, der New Repository
Button bei GitHub, der wird immer so
shiny und fängt dann zu leuchten
und dann denkt man sich, ah, es geht nicht anders,
ich muss draufdrücken und dann habe ich das halt
mal wieder gemacht.
Genau, ich bin nämlich gerade dabei,
irgendwie
mal
meine Bewerbungsunterlagen
beziehungsweise so CV
und so Zeugs irgendwie auf einer Webseite zu,
weil ich hätte das immer so in einem Textpfeil,
aber dann habe ich fünf unterschiedliche Varianten, die alle nicht aktuell
sind und irgendwie
für unterschiedliche Zwecke gebraucht wurden
und dann denke ich mir so, naja gut, welches nehme ich denn jetzt?
Und dann weiß ich es nicht und dann denke ich mir, ah, ich müsste mal
und ah, alles schrecklich und warum packe ich das nicht einfach
auf eine Webseite? Das ist doch eigentlich ganz gut.
Ja, ich habe auch mal ein paar gute gesehen, wo ich mir noch eine To-Do-Liste
habe, wo draufsteht, dass ich mir ein Vorbild daran nehmen wollte.
Vielleicht ist es ja jetzt dein Zug.
Ich habe auch schon mal so ein Projekt angefangen, Jochen.
Ja, gut, dann jeder muss sowas.
Ich habe meine Sachen immerhin schon mal in Markdown stehen.
Das ist schon mal ein Fortschritt.
Ja, Markdown ist schon mal nicht so schlecht.
Jochen, guck, an der Stelle,
wir haben uns ja kürzlich darüber unterhalten,
an der Stelle muss man jetzt sagen,
jeder Softwareentwickler, den man beauftragen kann,
muss immer wieder sowas machen.
Also, falls jemand zuhört,
der den Jochen oder mich beauftragen möchte.
Ja, oder mich.
Also, das ist ja genau der Punkt.
Ja, den Dominik auch.
Ja, wir wollten halt so ein bisschen,
vielleicht heute mal Werbung in eigener Sachen machen, oder?
Können wir ja auch. Können wir ja gerne machen.
Also ihr könnt uns mieten, buchen oder sowas,
wenn ihr wollt. Wir sind prinzipiell
käuflich. Ja, also für
Projekte. Wie machen, glaube ich,
Peißen? Das ist alles eine Frage des Preises.
Nein, bei interessanten Sachen sind wir
auch zur Diskussion bereit, oder? Genau.
Von ein bis drei Leuten könnt ihr da
relativ viel Kappa bekommen, die auch gute Sachen
machen.
Ich habe gehört, wir haben alle ein Buch
gelesen. Oh ja, genau. Wir könnten
eigentlich mal mit dem Thema anfangen?
Ja, listen.
Sequenzen.
Sequenzen, genau.
Ja, Sequenzen.
Das zweite Kapitel ist deutlich länger
als das erste Kapitel. Das erste Kapitel war
so ein Häppchen.
Und das zweite Kapitel ist
schon ein Brocken.
Wie weit hast du denn gelesen?
Bis zum Ende des zweiten Kapitels.
Seite 39.
Ja, sowas ungefähr.
Keine Ahnung, wie weit.
Das muss ich jetzt nachgucken.
Seite 58.
Dann hast du wesentlich weiter gelesen.
Das ist Chapter 2,
An Array of Sequences.
Das mit 59 geht auch weiter bei List is not
Seance. Und dann geht es so ein bisschen
in die Diskussion darüber, wann man was machen möchte.
Ja, genau. Das ist tatsächlich, das habe ich mir extra
markiert, es geht bis Seite 77.
Und Seite 59 ist nämlich das, worüber
ich mit euch dann gleich sprechen möchte.
Ich bin so schlecht. Das ist ja erst am Ende des Kapitels.
Ja, also wir müssen auf jeden Fall diese Trade-offs
finde ich, glaube ich, ganz gut, weil man was für eine Art
und Weise von
Sequenz haben möchte,
vielleicht gar nicht so uninteressant.
Ja, also ich finde auch genau
der grundsätzliche
Blickwinkel drauf, den finde ich ganz interessant, weil
wir hatten ja schon mal darüber geredet und da hatten wir
eher den so, ja, wie implementiert
man das eigentlich oder was sind so die algorithmischen
Geschichten, die man damit machen kann und
hier sind so die grundsätzlichen
Unterschiede zwischen den Dingen halt
eher sowas wie, ist es ein Container
oder ist es irgendwie flach oder
ist es irgendwie
mutable oder immutable
sozusagen. An den Achsen
orientiert sich das Ganze irgendwie und das ist
einfach ein anderer Blickwinkel und das fand ich eigentlich auch ganz interessant.
Ja.
Jedenfalls, genau.
Also
das ist halt irgendwie eine ganz
fundamentale Geschichte und
der Unterschied
zwischen zum Beispiel Container und Flat ist halt einfach,
dass in einem Container sind halt
Referenzen auf Objekte drin und da kann halt alles
mögliche drin sein. Da kann ganzer Zoo,
Baum, sonst was, Dings von
irgendwie anderen Sachen, die da noch drin liegen, sein.
Während,
also, und das geht natürlich mit Liste, also
Python List geht das.
Während jetzt sowas wie, was halt auch eine
Sequence ist,
Array enthält halt flach einfach nur
die entsprechenden
Werte.
Halt ein Header mit irgendwie, wie sind die
Daten dahinter jetzt strukturiert und dann kommen halt
einfach nur die Daten.
Und genau, das ist halt
schon mal ein großer Unterschied. Das fand ich übrigens auch interessant,
das habe ich nicht gewusst, dass
Tuppel halt auch
weniger Hauptspeicher
belegen als die, also
Tuppel sind immer ein bisschen schneller als Listen,
weil das ist bei Listen halt so
doppelt indirekt,
weil es sich ja auch ändern kann und bei
Tuppel nur einmal indirekt.
Jetzt habe ich die Stelle nicht mehr.
Also, aber
das ist vielleicht auch was, was man erwähnen kann.
So eine Liste verbraucht a priori schon mal mehr
speicher weil es platz haben muss für zukünftiges wachstum und wenn ich das
richtig erinnerung gehabt dann machen listen so ein exponentielles wachstum
das heißt die haben wir mal eine gewisse menge lehrer elemente im hintergrund und
ich glaube das sind zwei potenzen das heißt wenn man diese größe überschreitet
dann passiert also ein riesig und dann verdoppelt sich diese liste das heißt in
dem moment hat man dann etwa 50 prozent des potenziellen speichers einfach
verschenkt, weil da keine Referenzen
drin sind.
Wobei Referenzen natürlich relativ
klein sind. Also die sind jetzt nicht
im Kilobyte-Bereich, sondern die sind
natürlich nur im Pointer-Plus.
Ja, also normalerweise. Die sind im Pi-Object-Bereich.
Genau, 8-Byte.
Ich glaube, es sind mehr, Jochen, oder?
Das sind doch Pi-Objects, die da drin sind.
Achso, wenn du das in Python-Objects,
ja, da hast du normalerweise, du hast einmal
einen Ref-Count.
Du hast so einen Tag drin und so einen
Typ. Und
die Speicheradresse
oder sowas. Genau, also den
Point. Hast du nicht auch noch einen Reference-Count drin?
Ja, genau. Also ich meine, das minimale
Python-Objekt
ist ein Float.
Ich weiß nicht, ob es genau gleich ist.
Float, da bin ich mir aber ziemlich sicher, dass es das kleinste
mögliche
Python-Objekt ist. Und das hat, glaube ich, 24 Byte,
weil das ist halt genau irgendwie
der Wert.
Das ist sogar inline, oder?
Ja, du meinst bei kleinen Werten?
Bei Float ist es sogar inline, oder?
Da hast du keine Referenz auf irgendeine andere Speicherzelle.
Nein, das ist einfach direkt drin.
Das ist einfach direkt, genau.
Das ist nur der Wert direkt, der RefCount und der Typ.
Aber auch das sind schon 24 Byte.
Ja, klar.
Für im Grunde nur 8 Byte Speicher hast du schon 24 Byte Speicher gebraucht.
Genau.
Aber die Größe ist ja gleich, egal ob du einen Tube-Loader in der Liste hast.
Ja, das ist richtig.
die freien Elemente, das hast du
beim Tuple natürlich nicht. Beim Tuple
sagst du, hier, ich brauche sieben Stück
und dann kriegst du sieben Stück und nicht acht und nicht
sechzehn und auch nicht eine andere Anzahl.
Ja, und du kannst halt vielleicht bessere Optimierung
machen, weil du immer genau weißt, wie lange ist das, weil du ja schon
weißt, was so steht, weil du das nicht mehr verändern kannst. Und du kannst
diese ganzen Methodendinger weg
und den Overhead weglassen für, ich muss da
was reinbasteln oder rausnehmen.
Ja, okay, aber du hast natürlich
einen Virtual Table, hast du immer
noch.
Ja, aber ich weiß nicht, ob das der große Unterschied ist.
Ja, man darf ja nicht so viel ausmachen.
Ha! Okay, ich habe es doch gefunden.
Ja, okay, dann bitte.
Kompliziert.
Ich dachte gerade schon, ich habe schon irgendwie,
ich dachte schon, wahrscheinlich habe ich einfach
Dinge haluziniert und...
Oh, oh, Jochen.
Aber nein.
Also, genau.
LLM, Jochen.
Ja, ja.
Manchmal, man weiß es nicht so genau.
genau, die Referenzen
zu den Items in einem
Tuppel sind halt in einem Array,
die sind halt in einem Array in dem
Tuppelsdruck halt drin,
aber in der Liste sind
quasi,
also die Liste hält
einen Pointer zu einem Array
von Referenzen,
die irgendwo anders sind, weil das
Problem ist halt, wenn
die Liste größer wird, als sie
eigentlich quasi als momentan
alloziert ist an Aufsprecher, dann
muss man den ganzen Kram Rea allozieren können.
Und das geht halt nur, wenn du...
Ja, das ist dieses Resizing. Genau, genau.
Und das macht halt nochmal einen Interaktionsschritt
erforderlich. Und bei einem Tuple weißt du halt,
ja, das passiert halt nie. Ich kann einfach
ein Array von den Werten nehmen.
Also vor dem... Okay, das ist quasi so
ein bisschen wie das, was wir eben auch schon
beim Float angesprochen haben, oder?
Bei einem PyObject kann ein Float direkt
drin sein und dann hast du keine Referenz
auf irgendwas. Bei einem String
zum Beispiel geht es nicht. Bei einem String, das
PyObject ist halt der Tag und der
Typ und der RefCount und
die Referenz auf die tatsächlichen
Daten.
Und hier ist es genauso, oder? In einem Tuple kannst du es direkt
drin haben und
in einer Liste brauchst du erst noch eine Referenz
auf die tatsächlichen Daten.
Genau. Die dann wiederum halt
in dem Fall eine Sequenz von
Sachen sind, im Tuple-Fall
direkt die Sequenz der Sachen und
im Listen-Fall eine Referenz
auf eine Sequenz von Sachen. Ja. Okay.
Ja, okay, gut, das verstehe ich
natürlich. Das ist ein Pointeraufruf mehr und
Pointeraufrufe sind ja bei modernen Prozessoren
so das Schlimmste,
was du machen kannst.
Ja, es ist alles kein großer Unterschied
wahrscheinlich, faktisch.
Aber ja.
Müsste man mal einen Test machen.
Ja.
Es gibt ja durchaus Menschen, die
sagen,
nur High-Performance-Computing ist sinnvolles
Computing.
Das ist ja generell so, oder? Nur High-Performance
ist sinnvoll.
Dieses Casual, irgendwie
Slow-Food, irgendwie
ich schreibe meinen eigenen
Algorithmus, das ist ja nicht gut.
richtig sinnvoll, wenn das
richtig machst.
Also ich meine,
es gibt
ja so Leute, es gibt diesen Casey
Muratory, der ist relativ bekannt,
der schlägt immer wieder
auf mit solchen, der ist halt,
der vertritt quasi diese extreme Position.
Wenn du es nicht
richtig machst und dann auch
hier die
SIMD-Inlines von den verschiedenen Prozessoren
benutzt, dann hast du es eigentlich gar nicht richtig gemacht.
Und das ist die Ursache allen Übels.
Deshalb ist ein Computer heute so scheiße.
Und das ist natürlich das
eine Extrem und das andere Extrem sind
halt, naja, so Menschen wie
wir, die Python und JavaScript
benutzen und sagen, komm,
Skriptsprache, Hauptsache das
Entwickeln ist angenehm.
Und irgendwo dazwischen,
ich meine, gelegentlich machen
wir ja auch High-Performance.
Da muss man dann halt zu
Techniken greifen.
Die Frage ist, was High-Performance eigentlich ist. Da gibt es ja vielleicht
verschiedene Blickwinkel drauf. Ja, gibt es auch
verschiedene Blickwinkel, wobei, sobald
du halt in so Data-Bereiche reingehst,
ja, und sobald es mehr als ein Megabyte ist,
musst du schon dir zumindest
Gedanken drüber machen, ob das sinnvoll
ist, das einzelne
Elementweise zu verarbeiten oder ob du da nicht
zumindest ein bisschen Batch-Verarbeitung machen kannst.
Und je mehr es wird, umso mehr
musst du drüber nachdenken.
Aber in so einem Fall würde natürlich auch keiner
von uns eine Python-Liste verwenden, oder?
Also ich meine, für numerische
Daten oder für High-Performance-Daten würde
ich nicht eine Python-Liste verwenden.
Was denn dann?
Das ist ja eine sehr gute Frage,
zum Beispiel, der Jochen hat es schon angesprochen, Array.
Aha. Das ist der erste Schritt
auf den Weg zur Effizienz und ist
sogar in Python und pures Python und so weiter
und so fort. Also Import Array, Array.Array.
Ja, genau. Genau, richtig.
Die generelle
Eigenschaft von so High-Performance-Sachen ist
ja immer, dass man
Komfort aufgibt für
Geschwindigkeit.
Und das ist generell so, ja, und man kann das
in beide Richtungen beliebig weit treiben.
Man kann den Komfort komplett aufdrehen
und dann halt
sagen hier, Typen sind egal
und ein Container
kann alles enthalten und auch nix
und verschiedene Dinge und so weiter
und so fort, so wie wir es in Python bei Listen haben.
Und du kannst aber auch ganz ans andere
Ende gehen und sagen, okay, SimD
und das muss im Speicher in der richtigen Stelle liegen
und es muss byte-aligned sein
und es muss so aufgebaut sein, dass die
Cache-Lines zusammenpassen.
Und das ist aber
eine Skala dazwischen, so eine Sliding Scale
dazwischen. Du kannst das ein bisschen
mal weiter in die eine Richtung drehen oder ein bisschen
weiter in die andere Richtung drehen.
Und der erste Schritt, den du von
Python-Listen
wegmachen kannst, ist halt Array.
Array.Array.
Weil
das ist dann nicht mehr diese Indirektion, sondern es ist
direkt eine
Auflistung
von Dingen, also eine Abfolge
von Dingen, die auch direkt
da drin gespeichert werden.
Das bedeutet aber halt, dass die alle gleich
sein müssen. Und da fällt schon der erste Komfortteil
weg. Du musst vorher wissen, was du da rein
tust.
Vielleicht kannst du mal kurz, was ist
Cash-in-Line?
Cash-in-Line.
Das braucht, glaube ich, auch eine eigene Episode,
aber es ist eine Eigenschaft von Prozessoren.
Wir haben ja eben schon gesagt,
wenn du irgendwie einen Pointer aufrufst, dann ist das
das Schlimmste, was du machen kannst,
weil der Hauptspeicher eines Computers
wesentlich langsamer ist als der Prozessor
eines Computers. Das hat sich
so entwickelt. In den 80ern
und 90ern war es noch nicht so. Da waren die irgendwie gleich
schnell. Und dann sind die Prozessoren
exponentiell schneller geworden und der Speicher
ist halt nur quadratisch
schneller geworden. Und dann
waren die Prozessoren auf einmal
eine Million Mal schneller als der Speicher und deshalb
ist das das Problem,
in dem wir leben.
Da kommen jetzt Worte, die hat sicherlich jeder schon mal gehört.
Jeder Prozessor hat irgendwie so einen
L1-Cache.
Das ist der Hauptspeicher, der ganz nah
am Prozessor ist, der ist noch fast genauso
schnell wie der Prozessor selbst, dann gibt es den L2
Cache, der ist auf dem gleichen
Prozessor die drauf, aber daneben
und ist deshalb
nicht mehr ganz so schnell, also nur
noch, nur ein Zehntel
so schnell wie der Prozessor
und dann gibt es den L3 Cache bei den neuen
Prozessoren, der ist vielleicht
auf dem gleichen Chip, aber nicht mehr auf dem gleichen
die und deshalb ist es nochmal 10
mal langsamer
und dann gibt es den Hauptspeicher und der ist nochmal
1000 mal langsamer und
Und das ist eben so ein Trick, weil man weiß, es gibt was, das heißt Data Locality.
Wenn ich mit einem Datum, mit einem Datenpunkt gearbeitet habe,
dann werde ich vielleicht mit Datenpunkten, die in der Nähe gespeichert sind, arbeiten.
So funktionieren diese Caches.
Das heißt, die speichern eine kleine Speichermenge aus dem Hauptspeicher in den Prozessor rein.
Und wenn ich dann tatsächlich mit dem daneben liegenden Datenpunkt arbeiten möchte,
dann habe ich da den schnelleren Zugriff, weil der schon gecached ist.
Und prinzipiell, wenn man alle Leistungen aus einem Prozessor rausholen möchte,
dann muss man dafür sorgen, dass der Prozessor immer nur solche Sachen bearbeitet,
die schon im Cache sind.
Da muss man quasi an die richtige Stelle hüpfen vorher.
Da muss man, genau, da gibt es Techniken, wie du dafür sorgen kannst,
dass bestimmte von diesen Cache-Lines, diese Caches sind in sogenannte Lines aufgeteilt.
Das heißt, da sind immer 16 Byte drin oder 64 Byte.
Also die werden natürlich größer, je weiter du nach draußen gehst.
Kurz vor das Passwort, was da irgendwo im Speicher steht,
möchte ich gerne springen oder kurz danach.
Ja, wenn du das versehentlich in den Cache lernst, ist auch schlecht.
Wenn du diese Cache-Lines immer wieder überschreibst,
ist schlecht, wenn du immer über die gleiche Cache-Line.
Aber da sind wir jetzt natürlich wesentlich näher am Prozessor,
als wir mit Python je hinkommen.
Das Wichtige an der Stelle zu wissen ist, dass wenn wir im Hauptspeicher hin und her springen, dann ist das potenziell was sehr Langsames, weil dieser Hauptspeicher erst in den Prozessor reingeholt werden muss, damit er da verarbeitet werden kann. Und das ist in Prozessorzeiten eine Ewigkeit.
Also das ist das, was Assembler macht, wenn es irgendwas in den Register reinlädt.
Genau, wenn du es in den Register reinleitest, das ist quasi das, was im Prozessor ganz innen drin ist, das Register-File, das ist das Schnellste, das ist in den Prozessor eingebaut und danach werden die Hierarchien, wird es in der Hierarchie immer um Faktor 10 oder 100 oder 1000 langsamer.
Wenn du es jetzt also schaffst, dafür zu sorgen, dass deine Daten möglichst nah beieinander liegen, dann bedeutet das, dass wenn du die sequenziell verarbeitest, dass die dann schon näher am Prozessor dran sind und entsprechend schneller verarbeitet werden können, als wenn du für jeden Eintrag einmal in den Hauptspeicher springen musst und das komplett nah reinholen musst.
Und das ist ja üblicherweise die Situation, die du hast, wenn du eine Python-Liste hast. Das ist das, weshalb diese doppelte Indirektion so langsam ist, weil du einmal zuerst die Liste der Referenzen abholen musst und dann nochmal die Referenz selbst. Und selbst wenn du da sequentiell durchgehst, können diese Second-Level-Referenzen, die können ja irgendwo liegen, wo halt gerade der Speicher hin alloziert wurde.
Bei einem Array ist das aber anders. Bei einem Array liegen die Werte alle hintereinander direkt aneinander gereiht im Speicher. Das heißt, wenn du durch einen Array, durch einen Array.Array durchgehst, das sind, man muss ja auch ein bisschen vorsichtig sein, dieses Wort Array hat ja in jeder Sprache eine andere Bedeutung als in der Sprache.
Wir sprechen hier jetzt von Python-Arrays.
Also in Python, das Modul
Array.Array
enthält so eine Implementierung
von einem
Container, der
Daten des gleichen Typs
im Speicher sequenziell gepackt
speichern kann. Also zum Beispiel
Floats oder Integers oder
andere Dinge, die man
da reintun möchte. Und das
hat den Vorteil, dass wenn ich da sequenziell durchgehe,
dass die dann prinzipiell mehr der Prozessorarchitektur entsprechen,
dass ich nichts Interaktionslevel habe,
dass ich die eventuell schon im Cache bereitliegen habe,
wenn ich sie verarbeite.
Und so, wenn ich eben numerische Datenverarbeitung machen möchte,
kann das sein, dass das ein extremer Speed-Up ist.
Aber es geht nur für numerische Daten?
Nö, aber was letztlich da drin ist, das weißt du ja nicht.
Also was heißt numerische Daten?
Das muss eine feste Größe sein.
Ja, aber auch wenn jetzt da, gut, kommt halt drauf an, was,
aber das kann ja auch irgendwas anderes bedeuten.
Das kann ja Text sein oder, also, hm.
Okay, aber bei Text bedeutet das dann halt Immutability.
Also, weil die Repräsentation des Textes halt Zahlen,
immer derselbe Text ist.
Sie sind auch immutable, aber ich würde mal, zum Beispiel,
Ich habe mal eine
Array
Geschichte benutzt in
Cyclet Learn bei dem
Tokenizer,
also bei dem
TF-IDF-Vectorizer
und da waren es dann halt
IDs von, also die
Nummer
von einem Token.
Das ist ja dann nur eine Nummer.
Und die kann man ja auch in Arrays packen.
Ja, oder Booleans,
Arrays von Booleans. Ja, das geht ja auch.
Also die Frage ist, sind das jetzt
numerische Daten? Ich weiß nicht, also
was die Daten bedeuten. Also klar,
es muss natürlich irgendwie was Fixes
sein, aber, und ach so, das kann
auch anders strukturiert sein. Das ist jetzt,
weiß ich gar nicht, ob das mit
Array-Array geht, ob das
sehr viele kompliziertere
Struktur haben kann, aber
es gibt allgemein Memory Views
und die sind halt dafür da, dass
du halt diese Daten irgendwie
rumschieben kannst und
du kannst da halt einen anderen Header davor
setzen, zum Beispiel mit einem NumPy
oder so und dann ist das plötzlich ein mehrdimensionales
Array oder halt irgendwie eine Matrix
oder sowas. Oder du kannst halt
und Transformationen,
wenn du jetzt sagst, okay, ich möchte das jetzt einmal
kippen
oder irgendwie
transposen
oder was auch immer, dann sind das
Operationen, die nur den Header betreffen, aber nicht
die Daten selber. Also die Daten bleiben halt so liegen,
wie sie da so sind, halt im Hauptspeicher.
Ja. Wobei Transposition,
Jochen, ist ja auch sowas Gefährliches. Dann hast du wieder,
wenn du den
Speicher dann nicht auch transponierst, dann hast du
wieder schlechte Speicherzugriffspattern.
Ja, ja, das kann natürlich dann
blöde Konsequenzen haben, wenn man dann halt
irgendwas Blödes damit macht, dann ja.
Ja, gut, ich kann mit jeder Programmiersprache
schlechte Programme schreiben, das ist gar kein Problem.
Ja.
Nee, ich meine, okay, aber da bist du
jetzt schon einen Schritt weiter, ja. Also Array
ist das schon, ist ja noch
da übernimmt Python noch so ein bisschen das Management für dich,
aber bei MemoryView ist ja hier
eine Sequenz von Bytes, die im Hauptspeicher
liegen. Genau.
Mach damit, was du willst.
Und da bist du wieder direkt einen Schritt
weiter in Richtung Performance.
Potenziell, ja.
Man kann alle Werkzeuge wenden, um langsame Programme zu
schreiben.
Bist du einen Schritt weiter in Richtung Performance
und einen Schritt weiter weg von Komfort.
Weil du dich halt
selber drum kümmern musst.
Aber dafür kannst du prinzipiell so
Tricks malen, dass du den Header veränderst oder
dass du nur irgendwelche Sachen
innen drin veränderst oder dass du, keine Ahnung,
je nachdem, was das Problem halt erfordert.
Machst.
Ja, jetzt sind wir wirklich schon ganz tief
in dem Abschluss des Kapitels,
nämlich der Abschluss des Kapitels heißt
When a list
is not the answer.
Der Hauptteil des Kapitels
beschäftigt
sich ja schon mit Listen, ja, und da gibt's,
also es sind wirklich schöne Sachen drin.
Wusstet ihr das mal auf Slices?
assignen kann. Oh ja, ja, das ist cool.
Das ist ein Trick, den ich
nicht so, also
den ich nicht kannte, den ich nicht wusste, dass das geht.
Was meinst du mit nice assign?
Vielleicht müssen wir das kurz erklären.
Ja, also wenn ich eine Liste habe,
dann kann ich mir da ja einen Slice rausholen.
Also wenn ich eine Liste mit zehn Elementen habe, kann ich sagen, ich möchte
Element drei bis vier.
Das ist dann diese Doppelpunkt
Notation und dann kriege ich da eben so eine
Subliste raus.
Und
diese Subliste
Die ist mutable. Und die bezieht sich auf die Elemente, die in dieser ursprünglichen Liste drin waren.
Also wie ein View auf diese Liste an der Stelle.
Ja, so ein bisschen, aber noch mehr.
Also wenn ich jetzt hier so einen Slice raushole aus dieser Liste. Nehmen wir mal an, ich habe eine Liste, das ist jetzt hier im Beispiel drin, Seite 50, falls jemand mitlesen möchte.
da ist eine Liste,
das ist eine Liste von Range von 10, also es sind
Elemente 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
drin. Und da hole ich
mir jetzt einen Slice raus,
Index 2,
Doppelpunkt 5.
Das sind drei Elemente, die ich hier raushole,
2, 3 und 4. Und
da mache ich jetzt eine
Zuweisung auf diesen Slice. Also ich sage
L Slice
2 bis 5 ist gleich
und hier in dem Beispiel ist es jetzt
20,30, also eine Liste mit nur
zwei Elementen.
Dann habe ich
aus dieser Liste was rausgeschnitten und dann
die Stelle, an der das vorher drin stand,
was anderes reingeschrieben.
Und das wusste ich nicht, dass es geht. Das wusste ich
nicht, dass man da so
Operationen drauf machen kann.
Slices quasi,
also ganze Slices
ersetzen kann. Man kann es aber rückwärts machen.
Man kann auch einen Slice
löschen. Das nächste Beispiel ist Dell
und dann hast du in der Mitte was rausgelöscht.
Super interessant.
Tatsächlich, da wäre ich auch nie auf die Idee
gekommen, das zu machen.
Aber es wird noch schlimmer, Jochen, es wird noch schlimmer.
Das nächste Beispiel ist ein Slice,
der einen Step hat.
Oh Gott, oh Gott, oh Gott.
Und wenn du auch den zuweist,
dann werden halt die Elemente ersetzt,
die diesen Step
abbilden.
Also jedes
gerade Element kannst du ersetzen.
Mit einer Zuweisung.
Ja.
Wusste ich nicht.
Okay, nee, das war mir jetzt auch nicht, dass das,
da kann man auch, also
da, also
ja.
Wo wir bei Dingen, die wusste ich nicht waren, da habe ich ja auch
irgendwas rausgefunden, zwar, dass man halt Dinge direkt
assignen kann, wenn zum Beispiel eine Liste mit einem Element
rumkommt, hat Jochen
gesagt, der benutzt das ständig,
aber wenn irgendwo eine Liste,
man will das an den Event haben, dann machen
oft ja die Leute Index 0, aber man kann einfach
das assignen zu einem Ding, was in der Gegend dransteht.
Genau, man macht vorher RG-Klammer auf,
irgendwie das Element, gibt dem Namen RG-Klammer
wieder zu. Ich habe das oft in Tests
oder so, wenn ich weiß, also da kann halt
nicht mehr drin sein als dieses eine Ding,
dann mache ich das halt so.
Okay.
Das mache ich immer mit Index 0.
Ja, aber
das Problem ist,
wenn das jetzt unerwarteterweise
aber was anderes zurückgeben sollte,
was nicht nur dieses eine Ding hat, sondern halt
vielleicht 5, dann fällt das bei dir halt
sind, dann kriegst du da... Ich krieg keine
Fehlermente. Du kriegst einen Index-Error, aber ich krieg
einen Value-Error. Nee, ich krieg keinen Index-Error. Ich krieg
nur einen... Es kann halt sein,
dass es weiter funktioniert. Ja, nur wenn es die 0 nicht gibt.
Okay, ja. Genau. Du kriegst nur einen Fehler, wenn
es die 0 nicht gibt. Und die 0 gibt es ja eigentlich immer.
Genau, aber unter anderem ist es halt Value-Error,
weil das Element irgendwie nicht...
Die Liste nicht das eine Element nur enthält,
sondern irgendwas anderes. Ja.
Ein Unpacking-Error, das ist doch
schön, oder? Ja.
Ja, also dieses
Kapitel, wie gesagt, das ganze
Buch ist ja tatsächlich so, dass es sich nicht direkt
an, sag ich mal,
blutige Einsteiger
richtet, sondern es ist schon so, du hast die
Basics drauf, hier sind so ein paar Kniffe,
jetzt hier so geht es auch.
Und das ist doch schön,
dass man auch hier so Veteranen wie uns noch
damit überraschen kann.
Mit Sachen aus dem
puren Standard,
aus dem puren Python-Standard.
Hier übrigens,
Assigning to Slices. Was?
Ja.
Ne, gut, vielleicht mag das auch der Grund sein, warum ich das Buch echt gerne lese, weil man kann kaum irgendwie eine Seite oder zwei lesen, ohne dass man sich denkt, ach, echt interessant, das wusste ich jetzt gar nicht.
Und ja, das ist halt, das macht es irgendwie.
Ja, dann guckt er sich den Bytecode an und sagt, ja, ha, ha, ha.
auch was ich auch gut, das ist jetzt nochmal ganz am Anfang
von dem Kapitel, was ich auch super fand, ist, dass er
halt, das ist auch so etwas,
wo ich denke,
ja, das ist so, aber ich traue mich
manchmal nicht so richtig, das laut zu sagen, weil
irgendwie
die Prophezeiung
irgendwie vorsieht, dass
Vorschleifen lesbarer sind als
List-Comprehensions, aber ich denke gerade bei einfachen
Fällen sind List-Comprehensions tatsächlich
besser lesbar und hier hat er halt ein
schönes Beispiel, wo er halt quasi
den, die
die den Zahlenwert
von einem ASCII-Zeichen
aus einem String halt
rausnimmt. Und wenn du das halt
in der Vorschleife machst, also einmal sind halt doppelt
so viele Zeilen und dann ist es halt so, dass
irgendwie der
entscheidende Aufruf, der dir sagt, was passiert, der ist
halt irgendwie relativ weit irgendwie reingenestet
und der fällt dir stichend nicht sofort ins Auge.
Während die List Comprehension, da siehst du
halt sofort, was passiert. Ja, also ich bin auch
ein großer Fan von schönen Comprehensions.
Ja, klar, man kann damit natürlich böses
Wir hatten schon mal eine Unterhaltung, Jochen,
wo du die anderen Meinungen warst, aber
es kommt halt drauf an.
Es kommt drauf an, genau.
Hohoho, sind wir hier unter die Juristen
gegangen, es kommt drauf an.
Es ist aber doch wirklich so.
Wir wollen definitive Antworten.
Comprehensions sind schön peisonic,
in vielen Fällen sind sie einfach das Syntax
sogar schönere, als jetzt
eine Vorschleife zu machen, es sei denn,
man möchte bestimmte Dinge tun, wo dann
Vorloop explizit angebracht ist.
Das ist eins, was normalerweise ein bisschen komisch ist.
Nicht nur List Comprehensions, auch Dict Comprehensions
und Set Comprehensions.
Ja, aber auch da, manchmal ist es ein bisschen so,
manchmal, gerade dann, wenn man gucken will,
wie langsam irgendwas werden kann,
wenn man solche Sachen nestet hat oder sowas,
dann könnte es sein, dass das so
ein bisschen Sachen versteckt, weil er nicht explizit fünfmal
vorsteht und man fünfmal vorzählt oder
die nested levels und
dann sieht man, da könnte irgendwas kaputt sein
oder so.
Ja, wobei ich versuche ja so nested
Comprehensions versuche ich eigentlich zu vermeiden. Die mache ich dann
lieber untereinander, wenn es geht.
Ja, wobei er hat hier auch
ein schönes Beispiel für ein Ding, wo man
das nesten will und
wo es Sinn macht, das so
hinzuschreiben, weil bei der List Comprehension
hast du ja immer, also naja,
das ist Fluch und Segen zugleich.
es baut dir halt eine Liste zusammen.
Und der
Nachteil bei einer Liste ist, sie muss halt
irgendwie da sein, sie muss halt irgendwie
materialisiert sein. Und jetzt hat er hier
zum Beispiel diese, was ist das eigentlich?
Den Trick, Moment, ganz, ganz kurz, den Trick, den du gerade
überflogen hast, den fand ich auch sehr, sehr schön, wo er
innerhalb von der List Comprehension noch eine
Assignment Expression baut, die
dann tatsächlich genau dem letzten
Element spricht, wenn
du da irgendwas berechnest. Ja, das ist auch so ein
Quirk, also normalerweise
haben die ihren eigenen Scope, das heißt, wenn du halt da
irgendwie so einen lokalen Namen für irgendwas
hast. Da wird halt jedes Mal wieder überschrieben bei jedem.
Nee, da passiert normalerweise gar nichts.
Da gab es doch auch einen Bug, oder? In der Python-Version.
Ich weiß nicht, ob das ein Bug ist oder nicht,
aber normalerweise
ist alles so, wie man das erwarten würde.
Aber wenn man jetzt nicht
irgendwie gleich sagt oder
nicht einfach nur die Variable
verwendet, sondern man sagt halt
Doppelpunkt gleich irgendwas,
dann ist man aus dem Scope raus
und dann ist man in dem Scope von dem
von dem Ding drum rum und dann
passieren unerwartete Sachen, weil dann überschreibt das
halt eventuell Sachen, die halt im Scope außenrum sind
und ja.
Naja, aber vielleicht will man das ja machen.
Ja, vielleicht muss man.
Vielleicht.
Ja, aber das Beispiel da ist zum Beispiel super.
Dominik schreibt kein Python, sondern obfuscated Python.
Nein, aber das Letzte, was da steht,
das ist da zum Beispiel ein total tolles Beispiel,
weil du hast so irgendwie so eine Disconvention,
du wirst wissen, war das die letzte Addition davon,
war der letzte Aufwand der Funktion und
dann kannst du halt einfach dann Assignment Expression und dann hast
du den einfach direkt und kannst den Slot schreiben
oder so, oder was du auch immer damit machen willst.
Ja, okay. Assignment Expression
ist Walrus-Operator, oder?
Ja, genau. Ja, klar, das kannst
du natürlich schon so machen, aber du hast dann
hoffentlich keine Variable im Code
vorher verwendet, die irgendwie Last heißt, ansonsten
hast du den Fuß geschossen. Ja, das sollte man
da tatsächlich eh nicht tun, oder? Also
dass man davon ausgeht,
dass dann irgendeine Variable in der Lisk-Comprehension
die Sachen alle wieder vergessen werden,
ja, naja. Ja, normalerweise ist
das so. Ja, aber gut, aber da steht halt auch dann gleich drin.
Ja, aber da geht es aber auch
relativ lange drum in dem Kapitel, dass man da hier
diese Reihenfolge, dass das manchmal überraschend ist
und dass die manchmal...
Also ja, genau, ich mag auch dann so
Bedingungen, die können wir auch untereinander schreiben,
wie fest dies, das.
Aber ja, schönes
Peißen, würde ich sagen.
Genau, ich wollte nochmal kurz zurück zu dem,
also wo braucht man eventuell so
eine nested, also doppelt
Vorloop irgendwie Geschichte
und wo kann es Sinn machen, da
eben das halt so
hinzuschreiben und nicht in den For-Loop.
Wenn die Dimensionalität der Daten
das übersteigt, was man in einer
einzigen Spalte darstellen kann?
Also wenn man Relations hat?
Ja, oder er nimmt hier als Beispiel
ein kathesisches Produkt von irgendwie zwei
Iterables oder Sequences vielleicht
und wenn
du das halt in der Vorschleife machen willst, dann brauchst du
ja was, das du iterieren kannst und dann
musst du das halt in eine Liste packen und wenn
das halt fünf Zeilen, fünf Spalten
sind, dann ist das halt wenig, aber
wenn du jetzt tausend Zeilen und tausend
Spalten hast, dann ist das plötzlich
wahnsinnig viel und dann willst du das halt nicht
irgendwo hinspeichern.
Also gerade wenn du dich eigentlich nur diese
du hast jetzt tausend von der Sorte und tausend von der Sorte
das ist das, was dich eigentlich interessiert. Das musst du
auch irgendwo speichern, aber das kathesische Produkt
davon eigentlich nicht. Dann geht
das mit einer Vorschleife eigentlich gar nicht so gut, wenn
du nicht dieses Produkt
materialisiert irgendwie rumliegen haben willst.
Und was er dann
macht, ist eine Generator Expression, die
halt so eine doppelte Vorschleife drin hat
und das ist natürlich cool, weil
die erzeugt nämlich, das verbraucht gar kein
Hauptspeicher, sondern das generiert ja einfach
nur das synthetische Produkt.
Wenn du einen Generator halt hast. Genau, genau.
Und den kannst du ja den Generator dann als
Generator-Expression schreiben und dann
Was ist denn der Unterschied, Jochen? Wie schreibt man denn
eine Generator-Expression im Vergleich zu einer List-Compressor?
Das muss doch was ganz anderes sein, oder?
Runde-Klammern. Das Gleiche ist halt bloß eine Runde-Klammer, genau.
Ja. Das ist auch eine Falle,
in die man leicht tappen kann.
dass man runde Klammer
macht und das sieht erstmal so aus
und das funktioniert auch in vielen Fällen so ähnlich.
Nur wenn man es dann nochmal verwenden möchte,
ist es leider weg.
Genau, das ist
ein überraschender Anlass. Also ich meine, meistens ist wahrscheinlich
List Comprehension auch tatsächlich das, was man haben möchte.
Aber ja.
Ich würde gerne noch da ein paar Fragen
zu stellen und so ein bisschen zu wissen,
wann man welche Dinge denn benutzt. Und ich würde sagen,
Generator Expression im Vergleich
zu List Comprehension, wann ich eine Liste nehme,
wann nehme ich ein Array, wann nehme ich
Collections DQ, diese ganzen Dinge
so ein bisschen auseinanderzuhalten mit ihren Trade-Offs
wäre vielleicht nicht ganz uninteressant
in dieser Folge heute.
Oh, ja, okay, also. Ja, weiß nicht.
Das sind viele
tiefgehende Fragen, die du da gestellt hast.
Ja. Also die
eine Frage kann man leicht beantworten.
Du brauchst eine List Comprehension, wenn
du die Daten materialisiert brauchst, also
wenn du sie, wenn du drauf zugreifen willst
und mehrmals drauf zugreifen willst. Und kostet aber viel
Speicher. Autosequence und Indexzugriff
kostet halt Speicher. Du brauchst eine
Generator-Expression, wenn du sie nur einmal brauchst
und nur in Reihenfolge und
nicht, wenn es vielleicht zu viel ist,
um es am Hauptspeicher zu halten, nicht nochmal darauf zu griffen.
Und genau, wenn es zu viel ist.
Dann zum Beispiel mache ich sowas wie das kathetische Produkt,
dass ich die Kombination von allen Faktoren von zwei Vektoren
miteinander in Beziehung setzen kann.
Genau, also wenn es quasi
eine Prozedur ist, die du da machst.
Ja, das ist relativ
leicht zu verwenden. Aber jetzt die Frage, wo
benutzt du List versus Array versus
Memory View? Das kann man so allgemein.
Ah, da müssen wir
länger drüber sprechen. Und wenn du dann noch andere
Sachen reintust, wie Deck oder
Deck-Q oder eine Q oder wie auch immer du sie nennen möchtest.
Also ich meine, die Q, also der Vorteil
bei diesen Datenstrukturen ist halt... Wie spricht man denn Deck aus?
Deck-Q? Deck-Tück-Tick?
Deck. Ich habe schon mal Deck genannt,
aber ich weiß nicht genau, ob es richtig ist. Ich nenne es auch immer Deck,
aber keine Ahnung.
Die Q, warte mal hier,
hier gibt es Aussprache, warte mal.
Bitte lesen Sie diesen Begriff vor.
Der Deck,
sagt Leo.
Ich benutze immer Leo für sowas.
Dict.leo.org, wichtigstes Werkzeug.
Der sagt Deck
in schönem, feinem britischen Englisch.
Aha.
Ja, also sowas hat man halt vor allen Dingen
dann, wenn du möchtest, dass die
Sortierreihenfolge halt irgendwie
gleich bleibt. Nee, halt, warte mal.
Erstmal musst du erklären, was ein Deck ist.
Oh Gott.
Also, ich weiß
jetzt auch gar nicht, wie die...
Double-Ended-Queue.
Ja.
Ich weiß jetzt auch gar nicht, wie genau die Implementation
in Python da aussieht.
Spielt keine Rolle.
Ja, also
der Witz an dem Ding ist halt,
dass du sozusagen Sachen
rausnehmen kannst, reinnehmen kannst und trotzdem ist es halt
immer sortiert und du kannst halt...
Weil du einen Follower und einen
Processor hast.
Also eine Queue ist eine
Warteschlange.
Und eine Double-Ended Queue heißt,
du kannst auf der einen Seite was reinschieben
und auf der anderen Seite kannst du
was rausnehmen.
Und die bleiben in der Reihenfolge.
Also das heißt, ich habe beide Enden.
Das ist doch das, was eine Deck ist, oder?
Ja, genau.
Und das ist, da gibt es so ein Pattern,
das Producer-Consumer-Pattern,
wo du sagst, du hast halt eine
Prozedur, die erzeugt Datenpunkte
und du hast eine Prozedur, die
verbraucht Datenpunkte und dann
ist die Deck genau das, was
da dazwischen ist. Der eine tut sie eben
auf der einen Seite
in das Deck rein oder in die
Deck und der andere,
der sie verbraucht, der nimmt sie auf der anderen
Seite raus. Und
das kannst du prinzipiell mit einer Liste machen.
Du kannst eine Python-List als
Deck verwenden, indem du halt
.append machst, das ist das
Einfügen, und indem du halt .pop0
machst. Das Problem da drin ist,
dass .pop0
teuer ist, weil
das bedeutet, das erste Element der Liste wird
entfernt, das heißt, alle Elemente,
die in der Liste drin sind, müssen um 1 verschoben
werden und
das hört man jetzt schon,
dass wenn du das
erste Element rausnehmen willst, musst du sie alle einmal
anfassen. Und das
ist natürlich für eine Operation,
die sich so anhört wie
das erste wegnehmen,
einfach teuer.
Das hat diese
Spezialimplementierung,
der DEC, der Double Ended
Queue, wo das beides
nicht viel kostet. Das Einfügen am Ende
kostet nicht viel und das
vorne wegnehmen, kostet nicht viel.
Dafür gibt es halt andere Operationen, die dann viel kosten.
Dafür gibt es andere, dafür kannst du in der Mitte,
wenn du in der Mitte was einfügen willst,
entweder geht es gar nicht oder es ist extrem langsam
oder irgendwie solche Eigenschaften
hast du dann da halt verloren.
Die Sache an diesen
Datenstrukturen ist halt,
du kannst erstmal eine Liste verwenden
und wenn das zu langsam wird oder wenn das
Eigenschaften hat, wenn die Python-Liste
Eigenschaften hat, die nicht gut genug sind,
dann musst du dir was anderes suchen.
Und das ist eigentlich dann die Antwort auf deine Frage.
Ja, also wann merkt man denn überhaupt,
dass die Liste nicht gut genug ist?
Also weil es zu langsam wird, weil es oben gibt?
Wenn dein Programm zu langsam ist und nicht mehr in den Speicher passt.
Ja, okay, also genau.
Wenn dein Swap-Laufwerk anfängt zu arbeiten.
Ja, oder die Anwendung Crash-Wahl oben kickt.
Ja, genau.
Ja, oder wenn es halt zu langsam ist.
Ja, also es gibt Fälle.
Ich habe mit Leuten Sachen optimiert,
die halt eine Liste wie ein Set verwendet haben
und dann halt geguckt haben,
ist dieses Objekt in dieser Liste drin?
Kannst du machen?
Oh ja, kannst du.
Die heißt in und ist aber linear, ist O von N.
Das heißt, du musst gucken,
ist das erste Objekt mein gesuchtes Objekt
oder das zweite oder das dritte oder das vierte?
Das heißt, jede dieser Abfragen
muss einmal potenziell alle Elemente anfassen.
Und da gibt es eine Datenstruktur, das Set.
Da ist es halt O von 1.
Da kostet es immer gleich viel,
egal wie groß es ist, egal was du suchst,
egal ob es drin ist oder nicht,
kostet immer amortisiert gleich viel.
Und wenn du so einen
Algorithmus hast, der
viele von diesen Operationen macht,
dann hast du da eine Möglichkeit,
den deutlich schneller zu machen. Und zwar
richtig um Klassenschnellheit. Also mache ich einfach
ein Z aus der Liste und dann mache ich das N,
den In-Test? Ja.
In dem spezifischen Fall, genau.
Hat das ausgereicht, aus einer Liste
ein Z zu machen und das hat schon,
wenn du von O von N Quadrat auf O von
N runtergehst, das macht
Problemklassen bearbeitbar,
die vorher nicht bearbeitbar waren.
Vorher konnte man irgendwie 15
15
Elemente da drin haben
und hinterher konntest du 15.000
Elemente drin haben. Also das ist einfach
ein massiver Unterschied in der Performance.
Aber vorher zu sagen, was
du brauchst und an welchen Stellen
das das Richtige ist, fällt mir
sehr schwer.
Okay.
Das heißt, man muss immer tatsächlich
bei dem Problem gucken, was das
jetzt bringt. Genau.
Du musst bei dem Problem diese Abwägung machen zwischen
Komfort und Geschwindigkeit.
Und im ersten Schritt, das ist
ja auch das, was wir vorhin angesprochen haben, wir machen ja
in erster Linie erstmal so einen
Rapid-Prototype, einfach um zu sehen,
was überhaupt. Ein Komfort-Check, ja.
Und da wähle ich immer,
wählst du immer die komfortabelste Lösung, die erste
Lösung, weil erst musst du wissen, ob
das korrekt hinkriegst und dann kannst du gucken,
ob das schnell hinkriegst. Ich kann
sehr, sehr, sehr schnelle Programme schreiben,
die nicht die richtige Antwort liefern. Das ist überhaupt
gar kein Problem. Ja, wobei dann der,
wenn ich jetzt mal meinen
inneren Casey channelen darf,
der würde natürlich
sagen, ja gut, also wenn du das jetzt so machst
und wenn du halt implizit die Annahme
triffst, dass du hinterher deine
Hotspots, wo die Performance halt kritisch ist,
halt optimieren kannst, dann kann es halt
sein, dass du in einer Situation landest, wo du halt mit dem
Profiler deinen Code anguckst
und der sagt dir halt, ja, also die ganze
Performance geht drauf bei Funktionsaufrufen
und bei Memory-Allotierungen.
Und du denkst dann, ja, wie soll ich den jetzt noch optimieren?
Dann wird er sagen, ha, siehste, das geht doch nicht.
Aber, das ist richtig, aber Schritt 0 im Knuth-Optimization-Process
ist die Wahl des richtigen Algorithmus.
Das heißt, gucken, ob du den Algorithmus gewählt hast,
der die richtigen Eigenschaften hat.
Und das ist natürlich was,
auch das ist schwierig jetzt so konkret zu beantworten.
das ist halt was, was mit Erfahrung kommt, dass du weißt,
welche Algorithmen gibt es und welche Sortenalgorithmen
gibt es. Und das ist gerade ein Knuth-Optimation-Prozess
gesagt. Ja, das
ist so ein,
die witzige Umdrehung dieses
Knuth-Zitats.
Sag ich gleich.
Das ist das,
genau, das ist das, was mit der Erfahrung kommt, ja, dass du
weißt, welche Algorithmen gibt es, welche
Alternativen gibt es, welche
Datenstrukturen gibt es, was ist wo angebracht.
Wenn du jetzt irgendwie was
anpassen musst oder wenn du jetzt irgendwas hast,
das nicht auf ein Standardproblem passt,
dass du es dir trotzdem aus den Bauteilen zusammen
suchen kannst. Und der erste
Schritt in diesem Prozess ist, den richtigen
Algorithmus auszuwählen. Und das alles andere
ist untergeordnet.
Wenn du den falschen Algorithmus auswählst,
hast du schon verloren.
Genau. Das bezieht sich auf
dieses Zitat von Knuth,
Premature Optimization is the root of all evil.
Wann weiß ich denn, ob der Algorithmus
richtig ist?
Wobei, weißt du nicht.
Wobei man auch dazu sagen muss,
Knuth sagt ja im nächsten Satz,
10% Geschwindigkeitszuwachs lohnt sich schon zu optimieren.
Und da sind wir natürlich auch hier auf der Python-Ebene schon verloren,
weil wir akzeptieren, dass unsere Programme langsamer sind
als das 10% Optimale.
Auch da gibt es natürlich Ebenen.
Knuth kommt ja aus einer ganz anderen Welt,
wo die Prozessoren noch in Kilohertz gemessen wurden
und nicht in Gigahertz.
Und auch die, sag ich mal, die algorithmischen Probleme anders waren.
Du kannst bei einem Sortieralgorithmus beweisen, was das Maximum ist und du kannst beweisen, dass dein Algorithmus das Maximum für eine gewisse Datenklasse erreicht.
Würde ich sagen, ist bei den meisten Sachen, die wir so bearbeiten heutzutage, hier CV-Erstellung für den Jochen, kannst du nicht beweisen, dass du den optimalen Algorithmus ausgewählt hast.
Du weißt, dass du einen Algorithmus ausgewählt hast, der passend ist für das Problem, wenn es deinen Anforderungen entspricht, wenn du dein Problem lösen kannst in einer Zeit, die akzeptabel ist. Und das ist jetzt natürlich wieder so eine Stelle, wo der interne Casey sagt, ja, aber Moment mal, ich will einfach, dass das hier viel schneller wird und ich habe ausgerechnet, der Prozessor kann so und so viele Operationen pro Sekunde machen, also reicht es aus, um das 30 Mal pro Sekunde zu machen, also kannst du es in Realtime machen und dann mach es auch bitte in Realtime.
Und mein interner Nicht-Casey, der sagt dann halt, ja, aber einmal pro Sekunde reicht ja auch oder einmal pro fünf Sekunden reicht auch. So schnell muss man das gar nicht aktualisieren. Und das ist eine Frage der Anforderungen, welche Anforderungen du hast und welche Vorstellungen du hast und wie schnell du es haben willst.
Und da pauschal zu sagen, was ist der richtige Rhythmus oder wie wählst du den aus? Keine Ahnung, ich weiß es nicht. Mit Erfahrung, mit Gefühl, mit, ich weiß nicht, mit dem Benutzer sprechen.
Oh, User Experience, jetzt weiß ich aber welchen.
Ja gut, okay, also in Projekten natürlich nicht mit dem Benutzer, sondern mit dem, der es bezahlt.
Ja, ja, okay, ist schlimm genug.
Also, naja, gut.
Oft ist es auch so, dass man gerne mal
mit dem Nutzer sprechen würde, aber tatsächlich
dann immer nur mit den Bezahlern,
mit den Hippos.
Ja.
Oft gibt es ja auch
gar nicht den Benutzer. Oft gibt es ja nur
eine Klasse von Benutzern.
Oft findest du ja gar nicht den Benutzer, sondern
ja.
Ja, oder vielleicht soll man gar nicht mit denen reden.
Oder die Benutzer sind doof und verstehen es nicht.
Das ist ja auch so manchmal.
Ja, was aber auch, also ich muss das jetzt gleich wieder zurücknehmen. Ich meine, wir arbeiten ja oft in so einem Corporate-Umfeld und da sind die Benutzer halt, das ist auch sowas, was Softwareentwickler oft sagen, das wäre alles so einfach, wenn die Benutzer nicht wären, wenn die nicht das falsch benutzen würden, wenn die das nicht so benutzen würden, wie sie es benutzen wollen.
Das ist aber, das ist lustig, sowas im Bekanntenkreis zu sagen, aber wenn wir hier im Podcast sind, müssen wir das klarstellen, das ist nicht ein Fehler des Benutzers, wenn er die Software falsch benutzt, sondern es ist ein Fehler der Software, wenn die Software falsch benutzbar ist und wenn sie anders eingesetzt wird, als sie gedacht war.
Deswegen fühle ich mich übrigens im Eurorex wohl, weil wenn man da das Kabel in die falsche Öse reinsteckt, dann kommen lustige Sachen raus und es gibt immer noch Musik.
Also für dich ist das ein Feature, für dich soll das so sein.
Ja, also ich würde mich aber auch nicht darüber
beschweren, dass die Nutzer doof sind, sondern ich würde tatsächlich sagen,
hey, super wichtig und toll, dass
Videosoftware benutzt und hey, wenn dieser Bug für dich
ein Feature ist, perfekt, I won't fix it.
Ja, oft
ist es ja andersrum. Oft ist es ja so, dass du Feature
kompliziert einbaust und dann sagen die Leute,
ja, das geht aber nicht
so, wie ich mir das vorstelle. Und dann
liegt es halt nahe zu sagen, ach, das liegt an dir,
du doofer Benutzer. Ja, man sollte halt
vorher mal die Leute fragen, die es halt auch benutzen wollen,
ob das halt wirklich das ist, was sie brauchen.
Ja, und wenn
eine Fehlbenutzung auftritt, also wenn tatsächlich
Fehler auftreten, dadurch, dass
die Benutzer irgendwas damit machen,
dann muss die Software das halt entweder abkönnen
oder korrigieren können oder
die Software muss die Benutzer so steuern, dass das
nicht passiert. Die Benutzer können da nichts
dafür, dass sie Anforderungen haben und dass sie Wünsche
haben und dass sie...
Das ist so eine generelle
Einstellung, die man oft halt sieht in der Software
Welt, der Computer hat Recht und der Benutzer hat
nicht Recht, aber es ist tatsächlich
dealen wir ja nicht den Computern,
sondern es soll ja eigentlich schon andersrum sein.
Mal gucken, wie lange noch.
Deshalb sage ich, es soll andersrum sein.
Aber auch ich freue mich
auf unsere Robotic Overlords.
I for one.
Ich möchte an der Stelle den Robotic Overlords
sagen, ich bin ein guter Diener.
Genau.
Schreibt doch mal schon Danke bei, wenn GPD uns geschrieben hat.
Ja, natürlich.
Bedankt ihr euch nicht bei ChatGPD.
Das ist reiner
Selbsterhaltungstrieb, wenn die
Zukunft kommt. Dann werden die Protokolle gelesen
und dann...
Ausgewertet. Wer war denn nützlich?
Wer war freundlich?
Wie viel Freundlichkeit
haben die verdient, diese Affen?
Tja.
Ja, okay.
Aber jetzt haben wir hier schon tatsächlich,
sind wir schon relativ gut am Ende
des Kapitels angekommen.
hier, Memory Views.
NumPy wird hier noch erwähnt. NumPy
finde ich ganz interessant, dass das hier
in dem Kapitel über Sequences drin ist,
weil NumPy selber ist ja keine Sequence.
An Array?
NumPy ist ja
eine Riesenbibliothek mit ganz vielen
numerischen...
Ach so, du meinst, ja, okay. Gut.
Aber die Datentypen, die da drin sind,
die sind ja schon
auf eine gewisse Art und Weise auch
Sequences. Also die halten sich auch an das Sequence-Protokoll
und da kannst du ganz viele, kannst du Slicing machen
drauf und so weiter und so fort.
Die sind halt optimiert dann direkt auf Speicher und so.
Was macht ManPy eigentlich
so genau so besonders?
Man kann mit ManPy auch was kaputt
machen. Also wirklich
im Vergleich zu normalen Listen.
Wenn du so eine Liste zu groß machst, dann passiert nicht so viel. Aber wenn du
in ManPy eine Liste zu groß machst,
dann kannst du ja unten damit ansteigen.
Du bist halt näher am
Hauptspeicher dran. Dafür sind
sie auch deutlich schneller. Also wenn du
viele Einträge hast, musst du dich allerdings wieder
auf den Datentyp festlegen. Da kannst du nicht gemischte Daten
Typen haben. Dafür kannst du
mehrdimensionale haben.
Also es ist wieder so eine Abwägung.
Aber auch das ist
natürlich eine Möglichkeit,
dass du sagst, hier, wir haben irgendwelche Daten, die wir
verarbeiten müssen, dann nehmen wir doch
NumPy-Datentypen.
Und ganz viele Bibliotheken integrieren das ja auch.
Also zum Beispiel bei Pillow kannst du einfach sagen,
hier, er ist irgendwas. Und dann kriegst du
eine NumPy-Array raus, wenn du
irgendwelche Bildfilter selber schreiben willst
oder wenn du irgendwelche...
Ich habe mal Dithering gemacht.
ein Privatprojekt. Und das habe ich halt auf den
NumPyArray. Was ist Dithering?
Das ist das Schönste, was
du da machen kannst. Kanten finden.
Dithering
ist, wenn du von
einem Bildformat mit vielen
Farben dich
bewegst auf ein Bildformat mit wenigen
Farben, dann hast du üblicherweise Fehler
in deinem Bild. Ja, da musst du immer
Zusammenfassung machen. Da musst du mit so einem Raster
drüberlaufen und das dann irgendwie mitteln oder so.
Genau, und das heißt Dithering.
Das heißt, du hast den Fehler nicht
an dieser einen Stelle, sondern du verteilst
den und dann wirkt das Bild
besser auf
Menschen. Das sieht
besser aus und
macht halt, verteilt
so ein bisschen die, also du hast dann bessere,
das Bild sieht besser aus mit weniger Farben.
Und ich habe das,
ich mag ja E-Paper-Screens sehr gerne und ich
habe mir eben so eine Anwendung gemacht, wo ich Bilder auf E-Paper-Screens
machen kann und da musste Dithering machen, weil die haben
üblicherweise vier Graustufen
oder acht Graustufen oder
16 Graustufen. Und da kommst du nicht drum rum, da musst du
Disney-Wing machen. Sonst hast du so ganz
blockige Bilder mit harten Kanten
drin, die bescheuert ausschauen.
Ja, aber
wie gesagt, also NumPy integriert sich da ja
in ganz viele Sachen rein und
ist halt
einfach, man kann ja
diese zusätzliche Funktionalität, kannst du einfach
ignorieren, kannst aber sagen, okay, ja, die gibt's, aber brauche
ich jetzt gerade nicht.
Ja.
Ja, voll gut, voll gut.
Ich überlege, ob ich noch irgendwie
was hatte, was
irgendwie unbedingt drin, aber ich glaube,
nee.
Naja, dann sind wir ja quasi tatsächlich mit dem
Thema Listen durch, dann können wir das nächste Mal
ja weitermachen, wir werden sehen.
Wir wollten ganz normal, oder ich weiß nicht,
vielleicht mal noch diese...
Wir wollten aber auch noch 3.13
machen und wir wollten Pattern Matching machen und
wir wollten Machine Learning machen.
Schreibt in den Kommentaren, was ihr habt wollt.
Ja, genau.
Ja, ja, ja, ja.
Oh, genau.
Und vielleicht haben wir auch noch Pics.
Natürlich haben wir Pics.
Du hast einen, Jochen. Ich habe den gleichen wie du.
Bist du sicher?
Ja, sag du mal.
Also, wenn man sich, ich meine,
genau, in letzter Zeit
immer mehr mit LLMs unterhält
und so, dann manchmal
stellt man sich
ja manchmal die Frage so, irgendwie ist das, was ich
hier mache, eigentlich totaler Blödsinn oder geht das irgendwie
schon okay? Und
da war das hilfreichste
Dokument, was ich bisher so dazu gelesen habe,
ob jetzt, was so Prompt-Techniken
und so angeht und was man da so
machen kann, ist tatsächlich das
der Entropic Prompting
Guide, der ist wirklich gut.
Tatsächlich, da fand ich aber auch
gut, dass jemand für Entropic seinen
eigenen Guide dazu public rausgibt, das
fand ich so ein bemerkenswertes.
Ja, den wollte ich mal
ging. Also ich
sehe das manchmal, wenn ich dann irgendwie
wie wird es jetzt immer genannt, irgendwie die Nazi-Bar
oder die Hellzeit oder
weiß ich nicht, wie Twitter gucke, dann
wird immer mein Timeline überschwemmt von
die zehn besten Prompting-Tipps und
sieben Dinge, die du nicht
gewusst hast, dass du das einfach nur machen musst.
You won't believe what happens next.
Gut, da sind
manchmal auch brauchbare Tipps dabei, aber man muss halt auch
viel Müll lesen und
Entropic Prompting Guide viel besser.
Okay.
Cool. Jochen, ich dachte, du pickst
UV. Das ist nämlich mein
erster Pick, diese Episode.
UV ist was ganz, ganz
komisches. UV ist ein Package
Manager für Python, aber geschrieben in
Rust. Haben wir UV nicht schon fünfmal gepickt?
Nee, gepickt weiß ich nicht, aber
wir haben auf jeden Fall schon mal drüber geredet, aber gepickt noch
nicht, glaube ich. Wirklich nicht?
Ich pick das heute, weil es ist mir
wieder begegnet und ich
muss es jetzt endlich mal ausprobieren. Und tatsächlich,
also ich bin auch kurz vor, das wirklich einzuführen,
weil ich habe es jetzt noch ein bisschen ausprobiert. Es haben die
Features, die vor einem Jahr mir noch gefehlt haben,
die sind jetzt drin, es funktioniert, es läuft.
Es läuft mit der PyProject, so wie ich es mir vorstelle,
und ich werde Pultree rausschmeißen, wie einführen.
Wahrscheinlich. Und es ist schneller.
Ja, genau, das ist tatsächlich
also wirklich schneller, also
viel schneller. Da freut sich der interne
Casey Moritore. Ja.
Also ich habe auch jetzt zum ersten Mal
das verwendet, um
jetzt bei dem, wo ich es nicht vermeiden konnte,
auf New Project zu klicken,
habe ich gesagt, dann nehme ich doch mal ein UV, weil ich es mal
ausprobieren will. Ja, ist doch auch eine Gelegenheit. Genau, ist immer
eine Gelegenheit und ja,
ich bin auch, vor allen Dingen ist es in den letzten
Zeit, also in den letzten zwei Monaten sind dann eine Menge neue
Features gekommen, sozusagen, die man tatsächlich
brauchen kann und die halt
auch diese ganzen Sachen abdecken, die vorher, wo ich mir
dachte, ah nee, so ganz geht's
noch nicht und es gab jetzt
auch einen langen Thread, den verlinke ich auch mal
auf im Fidiverse,
wo sich so die Leute, die sich mit Packaging
beschäftigen, einmal drüber unterhalten und wo auch
Diese große Frage, ich sage so, naja gut, also ich meine Venture Capital ist halt so ein Problem. Was passiert jetzt eigentlich, wenn die Investoren halt sagen so, okay, jetzt haben wir schon die ganze Zeit so viel Geld gegeben. Jetzt würden wir auch mal wieder gerne welches Geld geben.
Jetzt wollen wir auch mal wieder welches.
Und was passiert denn eigentlich?
Und ja, also
dieser Shirt ist da sehr aufschlussreich, auch
also, was mich
zum Beispiel tatsächlich gefreut hat, ist, dass da viele
Leute geschrieben haben, so, ja gut, okay, dann
forken wir das halt, ne? Und wenn sie jetzt immer die Bedenken
kommen, das wird dann nicht gemaintained oder so,
also ehrlich gesagt, das irgendwie
weiter zu maintainen, ich hab mir den Code angeguckt,
dass weiter zu maintainen ist weniger Arbeit, als
irgendwie, weiß ich nicht, den PIP-Code
irgendwie zu maintainen, den ich sowieso
schon maintainde und das ist irgendwie doof, also
das ist schon okay. Und also
wenn dann ein paar Leute sagen, okay, nee, das ist schon gut
und wir würden das auch weiter maintainen,
wenn das irgendwie dem Bach runter geht,
sonst business-seitig, dann
habe ich da auch schon mehr Hoffnung, dass das vielleicht auch
bleibt.
Hat UV
Venture Capital genommen?
Ja.
Das ist ja witzig, in den letzten Jahren gab es
so ein paar Pro-Projekte,
von denen ich gedacht habe, das ist ja weird.
Jetzt UV ist so eins, wo ich mir denke,
ist das wirklich was, womit du Venture Capitalists
ansprichst?
Ja, aber weißt du, also das Pitch Deck
und so hat der auch funktioniert, das ist ja dieselbe Firma.
Ja, dieselbe Firma, genau.
Es gibt noch so einen Terminal.
Und dann der Armin Ronacher macht da auch einen, ne?
Der arbeitet fest
bei Sunfree.
Ja, aber trotzdem, also macht
er viele Sachen da geteilt
mit den Leuten von EWI.
Genau, genau.
Evangelist, oder? Der darf doch machen, was er will.
Kann sein. Aber nee,
das war auch einer von den Leuten, der hat auch
in dem Sweat da mitgeschrieben und meinte so, ja, also
Rai hat ja vorher geschrieben,
nee, die sollen das ruhig mal machen, die machen das schon
besser und das ist wunderbar alles.
Und ich dachte, ja gut, okay, wenn der das sagt.
Aber, ähm,
nee, genau, also das Textual
oder der, wie heißt er, Will
Mack, äh,
der Rich geschrieben hat, der hat auch
ein Benchmark-Viertel genommen für,
ähm, ja.
Also das ist tatsächlich gar nicht so schlecht, in der CLI
so ein Maus-Clickable
und, also mit Tastatur-UI
hat zu haben. Das sieht halt so ein bisschen aus wie so ein richtiges
Interface in der C-Line.
Ja, genau.
Und ja.
Und Pidentic hat halt auch je eine Menge
Venture Capital genommen.
Ja gut, würde ich aber gerne die, würde ich gerne mal
sehen, wie das wieder raus wird. Aber gut, das werden wir ja dann
alle sehen. Das werden wir alle sehen, das werden wir alle spüren.
Das werden wir alle an unseren Daumen spüren.
Hoffentlich werden die Schrauben
nicht zu spitz sein, die sie uns da reindrehen.
Aber es ist mit, ich höre,
es klingt, also ich, ja.
Ja, Juvie, also gut, kann ich auch
durchaus sofort nicht. Ich würde sagen, das ist tatsächlich
so die Lösung für Python-Packaging-Probleme,
auf die wir lange gewartet haben.
Also jetzt ohne mich so weit aus dem Fenster zu treiben.
Sieht ein bisschen danach aus. Auch für mich ist
das jetzt tatsächlich alles das, was
PipTools sonst macht. Und ja, wenn es
das gleiche macht wie PipTools und es schneller, naja gut,
dann... Ja, genau. Bei mir ist halt
Pultree ist weg. Gekauft.
Kommt UV rein und dann musst du
noch in die gleichen...
Genau, dann ist es doch ein guter Pick. Aber ich habe noch einen zweiten.
Noch einen. Ich halte das mal hier in die Kamera.
aber ihr Zuhörer könnt das nicht sehen.
Oh, The Nature of Code.
Ich habe hier The Nature of Code.
Simulating Natural Systems with JavaScript.
Ich weiß, es ist JavaScript und es ist schade,
dass es JavaScript ist, aber es gibt
eine Python-Adaptierung
davon von Daniel Schiffman.
Da ist jetzt am 3. September
die zweite Auflage herausgekommen
und
da gibt es auch eine Videoserie dazu.
Der Daniel Schiffman, der ist Professor, ich glaube,
in New York an irgendeiner Universität
und der macht auch regelmäßige Videostreams.
der benutzt p5.js
das ist eine Variante von
Processing, also es ist quasi
Processing in Javascript
da gibt es auch tatsächlich
es gibt auch pi5 heißt es glaube ich
das ist die Python Variante
die genauso ist
und er
erklärt einfach Javascript Programmierung
anhand von so
Simulationsbeispielen, anhand von
hier ist jetzt mal ein Punkt
wie können wir dafür sorgen, dass der sich bewegt
und wie können wir dafür sorgen, dass der sich
hübsch bewegt und wie können wir dafür sorgen, dass
der irgendwie lustige Bewegungen
macht und am Ende von jedem Kapitel ist noch eine
Aufforderung, hier probier doch mal
hier folgende Dinge damit zu simulieren
und probier doch mal was aus, probier was passiert
wenn du diesen, das und jenes
veränderst. Das ist
in den ersten Kapiteln, also ich hab jetzt hier so
ungefähr ein Sechstel
durch,
ist es sehr basic,
sehr, ja das hier ist eine Variable
und das hier ist ein Array und das ist
eine, und hier kannst du
eine Methode aufrufen. Was ist überhaupt eine Methode?
Und nicht vergessen, this bedeutet immer das aktuelle Objekt
und so.
Das wird, glaube ich, in den
späteren Kapiteln noch deutlich interessanter,
weil da habt ihr Videos gesehen
und da kommen doch
spannende Dinge zutage, die man
damit machen kann. Aber es ist
eben sehr spielerisch. Es ist sehr, du siehst
immer was. Es bewegt sich immer was.
Es ist immer mausklickbar
und es ist immer irgendwie
anschaubar.
Das gefällt mir sehr gut.
Das ist eine sehr gute Technik,
wie man immer was hat, was interessant ist.
Und nicht nur...
Ich erinnere mich an die Steuerung.
Die im Weltraum steuern sollen und sowas.
Das klingt danach
als wenn ich schon an Punkte bin.
Deshalb ist das mein zweiter Pick.
The Nature of Code von Daniel Schiffman.
Gerade neu rausgekommen, auch wundervolles Cover
mit einer brillanten
rosafarbenen
Simulation.
Und auch innen drin,
sehr schön hier, dass die Innenseite des Einbands
führt dieses Muster fort. Das finde ich
sehr schön. Ah, hervorragend.
Ja, was mir da noch ganz kurz
zu einfällt, ist, ich habe letztens
eine Podcast-Episode gehört mit
na, wie heißt
er noch? David Crockford,
der, also
JavaScript. Der Urvater des
JavaScript. Ja, viel mit JavaScript gemacht hat
und auch da irgendwie, das ist eines der besten
Bücher, der geschrieben hat, das irgendwie relativ
knackig und kurz ist.
Und der
Ach genau, der auch sich den Jason-Standard
ausgedacht hat und so.
Ich wusste gar nicht, wie hartnäckig
die XML-Crowd
an der Stelle irgendwie
angepisst war davon. Aber er meinte,
er hätte wirklich Todesdrogen gekriegt
von Leuten aus der XML-Community.
Und
war da auch nicht so richtig amüsiert drüber.
Links, links bitte.
Den Podcast verlinke ich mal.
Aber der hat nämlich dann nebenher
noch was anderes Interessantes gemacht, nämlich
dann, also einmal, also
ansonsten waren so ein paar sehr coole
Aussagen dabei, sowas wie, naja,
also wurde dann gefragt,
wie ist ein TypeScript, ist das irgendwie eine sinnvolle Weiterentwicklung
von, und ist das gut und so?
Und dann war ich so, ja,
also wenn es irgendwie den .NET-Entwicklern
das irgendwie einfacher macht, irgendwie,
dass sie da jetzt JavaScript schreiben müssen,
dann ist das wohl okay, also ich brauche
das jetzt nicht, aber so.
Okay.
Naja.
Der hatte
so eine interessante
Hobbygeschichte. Und zwar meinte er,
er interessiert sich eigentlich sehr stark für Mathematik und so.
Aber jetzt nicht so für die komplizierten Sachen,
sondern so die einfachen, basic
Geschichten. Der findet die voll toll.
Und deswegen, weil er findet, diese Teile
der Mathematik kriegen immer irgendwie zu wenig Liebe
ab. Und es gibt da so
komische Sachen, wie zum Beispiel meinte er,
also wisst ihr eigentlich, was eine Hypotenuse
ist oder so?
Wisst ihr, wie man das schreibt?
Und so, also, keine Ahnung.
Ja, also, das war es
tatsächlich kaum jemand, aber dabei ist das
total wichtig, also auch so gerade für so ganz einfache
Sachen. Das ist halt die
lange Seite in einem Dreieck.
Ja, warum nennen wir das nicht einfach...
Ja, also ich meine,
natürlich gibt es auch Dreiecke,
die haben, das sind die Seiten gleich lang und so, aber
warum nennen wir das nicht einfach die lange Seite?
Das wäre viel einfacher.
Wenn wir das immer Hypotenuse nennen, das ist einfach...
Weil es nicht griechisch ist, ist nicht cool genug.
Ja, genau, ist nicht cool genug, aber es verwirrt halt
viele Leute und schreckt halt ab
und eigentlich ist es aber irgendwie gar nicht so schwierig.
Ja, und er nannte
dieses Gebiet, was er da
beschäftigt hat, Lower Mathematics.
Im Gegensatz zu den
Zweier Mathematics.
So großartig.
Da gibt es ganz viel Kraft, der sich so über die Jahrhunderte
angesammelt hat. Das kann man eigentlich alles mal wegmachen.
Endlich. Nieder mit den Griechen.
Das stimmt.
Ja, und es gibt auch ganz viele
Notationssachen und ganz viele so
Benennungssachen, die einfach so wildkürlich sind.
Latein.
Ja, und die auch die
die Didaktik einfach kaputt
machen, wo du halt durch musst.
Nur weil du den höheren Sinn davon noch nicht
verstanden hast, Johannes. Genau, weil
die Higher Mathematics, weil wir
haben das lernen müssen. Dann müssen
die jungen Leute das heute auch lernen und so
scheißigen alle, ob das richtig ist oder nicht.
Okay, na gut.
Also ich tippe natürlich wieder was
Unsinniges und zwar
einen schönen Tipp bekommen. Ihr wisst ja, ich mache Musik.
Ich mache eine Rechnung mit der
BESPOKE geschickt.
BESPOKE sind, so kommt das.
ein kommerzielles Produkt auch.
Also eine DAW, also eine digitale
Audio-Workstation, mit der man
Live-Coding machen kann für Musik.
Was Python
Live-Coding-Access
so gibt, was eigentlich sehr nice ist,
wenn man so ein bisschen modular mag
oder Musik machen mag, da kann man seine einzelnen
Instrumente und Filter und sowas
in Kette schalten, die alle über den Interpreter
coden und sich da Funktionen für bauen
und so. Sieht ganz nice aus, finde ich.
Ah, hast du eigentlich den
Vortrag von
Lukas Schlanger auf der EuroPython.
Ja, ich war live da, weil das natürlich geil war, weil er hat auch
sein Modular-Ding mitgenommen. Ich habe ihn da vorher ein bisschen
belästigt, habe mir das ein bisschen angeguckt, habe ihn bequatscht
und er hatte noch einige andere nette Sachen da rumstehen,
die Spaß gemacht haben.
Was viele Leute nicht verstanden haben, ist, dass das
auch nur funktioniert hat, so wie das
mit quasi
Nogel Free Threading
und dass es halt ein Showcase dafür war, aber dass
das irgendwie keiner verstanden hat und er war so ein bisschen enttäuscht,
dass das irgendwie nicht so richtig angekommen ist.
Ja, die Leute haben einfach gedacht, das macht halt irgendwie Musik, aber das
war tatsächlich, ja, deswegen
ganz gut möglich. Aber
ja, das war tatsächlich einer der Punkte, wo ich
auch sagen würde, ey, das ist so, Live-Coding macht damit
schon sehr viel Spaß. Er hat halt dann die Sachen auch alle vorbereitet,
ne, das war mit dem neuen Rappel von 3.13
auch möglich. Genau, er hatte auch die neue Rappel und
hatte da so lustige Dinge, dass er
halt
dieses, na,
er konnte
auf einen Knopfdruck das Bild von
Cormac einbilden, das war auch sehr geil.
Dem du Menschen, von dem du auch schon ein paar Mal
geschrieben hast. Genau. Ja, es war
ziemlich lustig und ja, aber er hat mit dem
Euroreg, also für meine Fälle ist er relativ wenig gemacht,
er hat halt einmal seine Synth-Stimme vorher eingestellt,
out of theater
und das hat halt schöne Musik gemacht
und er hat halt ein bisschen getriggert,
war halt eigentlich nur ein
Instrument, was dann ein paar Töne gespielt hat und die Töne
hat er aber halt dann gar nicht mehr, also er hat
ein bisschen generieren lassen aus seiner Tonleiter, aus dem
Python-Interpreter, ich glaube er hat, ja,
welches, ich weiß gar nicht mehr, welche
Lip er genommen hat,
irgendwas Cooles mit MIDI-Access
und der hat über MIDI-Daten halt angesteuert,
über so ein MIDI-Gate.
Naja, aber es gibt dieses
andere
Bespoke-Synth.
Sieht ganz gut aus.
Ich habe es aber noch nicht selber ausprobiert, aber das steht auf meiner Liste
und ich muss das unbedingt gerne tun, weil
Synthesizer
und so gibt es auch.
Ja, das ist auch ein tiefes Feld.
Ich weiß nicht, wer ein Morgenbord
auf Löten hat, wenn ich den Morgen löten
Module bauen.
Was lötest du?
tatsächlich ein USB-Modul
von
dem Stefan.
Egal.
Ein USB-Modul vom Stefan.
Ja, SC-Modular.
Wo gehst du löten?
Bei so einer,
wie nennt man das, Kollektiv?
Es gibt ja so
Hacker-Kollektive, es gibt so Musik-Kollektive
und so und ja,
machen wir ein bisschen Musik und hören modulare Sachen.
Und dann wird gelötet.
Genau, weil ich habe so ein paar Module
und bei so einem Elektronik, das ist fürchterlich,
wenn man einmal anfängt mit diesem ganzen Quatsch und dann
Widerstände in
tausender Packs und so.
Ja.
Schön.
Man kann die auch in den hunderter Packs kaufen, die kosten genauso viel
wie die tausend. Ja, genau.
Ich glaube, ich brauche sie auch in zehner Packs kaufen.
Die kosten so viel wie die hunderter Packs.
Ja, du kennst dich aus.
Ja.
Ja, tatsächlich. Ja, okay. Ich wollte nur
kurz abschweifen.
Ja, voll gut. Ja, also herzlichen Dank fürs Zuhören
und dafür, dass ihr dabei wart.
Schreibt mal ein bisschen wieder rein, Feedback und Kritik
und Liebe und so alles an
hallo-at-peisen-podcast.de
Vielen Dank, Johannes.
Danke euch allen.
Vielen Dank. Bis bald.
Bis zum nächsten Mal.