Diese Fragen prüfen nicht einzelne Seiten, sondern was zwischen ihnen liegt: dasselbe Prinzip in Sprache, Bibliothek und Werkzeug, und die Stellen, an denen zwei ähnlich aussehende Dinge verwechselt werden. Die Sammlung wächst mit jeder fertigen Themenseite.
Antwort anklicken, die Begründung erscheint darunter. Es wird nichts gespeichert und nichts ausgewertet.
Sprache
[0, 0, 0]
Richtig. Bei Listen wiederholt der Stern die Liste, er rechnet nicht mit den Elementen. Für elementweise Multiplikation braucht es eine Comprehension oder NumPy.
[0]
Das wäre das Ergebnis, wenn der Stern die Elemente multiplizierte. Genau diese Verwechslung ist gemeint.
Einen Fehler
Die Operation ist gültig und häufig genutzt, etwa um eine Liste vorzubelegen.
Eine Funktion ist als def sammeln(wert, bisher=[]) definiert und hängt wert an bisher an. Beim dritten Aufruf ohne zweites Argument enthält die Rückgabe drei Werte statt einem. Warum?
Der Defaultwert wird einmal bei der Definition erzeugt und von allen Aufrufen geteilt
Richtig. Eine veränderliche Liste als Defaultwert lebt an der Funktion weiter. Als Defaultwerte taugen nur unveränderliche Objekte, sonst None und die Liste im Rumpf anlegen.
Python merkt sich die letzten Aufrufe
Es gibt keinen solchen Mechanismus. Es liegt allein am geteilten Objekt.
Die Funktion wurde rekursiv aufgerufen
Nein, jeder Aufruf ist unabhängig. Nur das Defaultobjekt ist es nicht.
Was ist der Unterschied zwischen einer Liste und einem Tupel, der praktisch zählt?
Tupel sind schneller
Der Unterschied existiert, ist aber selten der Grund für die Wahl.
Ein Tupel ist unveränderlich und darf deshalb als Dictionary-Schlüssel dienen
Richtig. Schlüssel müssen unveränderlich sein, weshalb ein Koordinatenpaar als Tupel funktioniert und als Liste nicht.
Tupel können keine gemischten Typen enthalten
Doch, das können sie. Der Typ ist bei beiden frei.
Ein R-Skript enthält b <- a; b[1] <- 0 und wird als b = a; b[0] = 0 nach Python übertragen, a ist eine Liste. Was ändert sich am Verhalten?
In Python ist danach auch a[0] gleich 0
Richtig. R kopiert beim Ändern, Python lässt beide Namen auf dasselbe Objekt zeigen. Beim Übertragen braucht es an dieser Stelle b = a.copy(), bei verschachtelten Listen copy.deepcopy. Dasselbe gilt für Objekte eigener Klassen und, in anderer Form, für NumPy-Slices.
Nichts, beide Sprachen kopieren bei der Zuweisung
Keine der beiden kopiert bei der Zuweisung. R kopiert erst beim Ändern, Python gar nicht.
Python meldet einen Fehler, weil a nicht verändert werden darf
Die Zuweisung ist gültig und gerade deshalb unauffällig.
Ein Zugriff auf einen fehlenden Wert, werte[10] bei fünf Werten oder lager["D"] bei fehlendem Schlüssel, liefert in R NA beziehungsweise NULL und in Python einen Fehler. Welches Verhalten ist für eine Auswertung sicherer?
Das von Python, weil der Fehler an der Stelle auffällt, an der er entsteht
Richtig. Ein stilles NA kann durch mehrere Schritte wandern und am Ende einen Mittelwert verfälschen oder zu NA machen, ohne dass die Ursache sichtbar ist. Wer bewusst einen Ersatzwert will, schreibt es hin, etwa mit lager.get("D", 0).
Das von R, weil das Programm weiterläuft
Weiterlaufen mit falschen Werten ist schlechter als ein Abbruch mit klarer Meldung.
Beide sind gleichwertig
Sie unterscheiden sich darin, wann der Fehler bemerkt wird, und das ist der ganze Punkt.
Ein laufender Mittelwert soll zwischen einzelnen Aufrufen seinen Stand behalten. In R wird er als Closure geschrieben, in Python als Klasse. Wann ist die Klasse die bessere Wahl?
Immer, Closures sind veraltet
Beide Formen sind gleichwertig, solange es nur um eine Operation geht.
Sobald mehrere Operationen denselben Zustand teilen, etwa zurücksetzen, Anzahl abfragen und Varianz mitführen
Richtig. Jede weitere Operation ist in der Klasse eine Methode; in einer Closure müsste man mehrere Funktionen zurückgeben, die auf dieselbe Umgebung zugreifen.
Nie, denn eine Klasse kann keinen Zustand zwischen Aufrufen halten
Genau das tut sie über ihre Instanzattribute.
Bibliotheken
Ein Array a hat die Form (100, 3), ein Array b die Form (3,). Was passiert bei a + b?
b wird auf jede der hundert Zeilen angewendet
Richtig. Die Formen werden von hinten verglichen, dort steht in beiden die 3. Nach vorne wird die fehlende Achse ergänzt und wiederholt. Typischer Fall ist das Abziehen von Spaltenmittelwerten.
Es gibt einen Fehler wegen unterschiedlicher Formen
Genau dafür ist Broadcasting da. Ein Fehler entstünde bei einer Form wie (100,).
Die Arrays werden aneinandergehängt
Das täte np.concatenate, nicht der Plus-Operator.
teil = original[2:5] und danach teil[0] = 999. Was ist mit original?
Es hat sich mitverändert
Richtig. Ein Slice liefert eine View, also ein Fenster auf dieselben Daten. Wer eine unabhängige Kopie braucht, ruft .copy() auf.
Es bleibt unverändert
Das wäre bei einer Auswahl über eine Bedingung der Fall, etwa original[original > 5]. Die liefert eine Kopie.
Es gibt einen Fehler
Nein, die Zuweisung ist gültig. Genau das macht den Fall gefährlich, denn nichts weist darauf hin.
Zwei pandas-Series mit denselben Werten, aber unterschiedlicher Indexreihenfolge werden addiert. Was passiert?
Die Werte werden der Reihe nach addiert
Das wäre das Verhalten von NumPy-Arrays. Pandas macht es anders.
Pandas richtet nach dem Index aus, nicht nach der Position
Richtig. Addiert werden Werte mit gleichem Indexeintrag. Fehlt ein Eintrag auf einer Seite, entsteht dort NaN.
Es gibt einen Fehler wegen unterschiedlicher Reihenfolge
Nein, die Ausrichtung ist gerade der Zweck des Index.
Auf einer Seite steht df[df["a"] > 1]["b"] = 0, und der DataFrame bleibt unverändert. Warum?
Zwei Zugriffe hintereinander erzeugen ein Zwischenergebnis, das eine Kopie sein kann
Richtig. Die Zuweisung trifft dieses Zwischenergebnis, das danach verworfen wird. Zeilen- und Spaltenauswahl gehören in einen einzigen .loc-Zugriff.
Die Bedingung trifft auf keine Zeile zu
Möglich wäre das, ist aber nicht die typische Ursache dieses bekannten Musters.
Zuweisungen an DataFrames sind nicht erlaubt
Doch, über .loc funktionieren sie zuverlässig.
Dieselbe Auswertung liefert in R sd(x) = 7.3967 und in Python np.std(x) = 7.0171, und pd.Series(x).std() wieder 7.3967. Was folgt daraus für das Übertragen von Code?
Voreinstellungen gehören zur Bibliothek, nicht zur Sprache; NumPy teilt ohne ddof=1 durch n, pandas und R durch n − 1
Richtig. Dieselbe Kennzahl kann innerhalb von Python je nach Bibliothek anders berechnet werden. Beim Übertragen die Voreinstellung nachsehen, nicht nur den Funktionsnamen.
Python rechnet ungenauer als R
Alle drei rechnen exakt, nur mit verschiedenen Formeln.
pandas ist fehlerhaft, weil es anders als NumPy rechnet
pandas folgt bewusst der Stichprobenformel.
Eine Matrix wird in R mit matrix(1:6, nrow = 2) gebaut und in Python mit np.arange(1, 7).reshape(2, 3). Danach wird je Spalte zentriert, in R mit m - colMeans(m). Wie viele Fehler stecken in diesem Ablauf?
Zwei: verschiedene Füllreihenfolge und falsches Zentrieren in R
Richtig. R füllt spaltenweise, NumPy zeilenweise, die Matrizen sind verschieden. Und m - colMeans(m) recycelt spaltenweise und zieht die Mittel an den falschen Stellen ab; richtig ist sweep(m, 2, colMeans(m)). Keiner der beiden Fehler erzeugt eine Meldung.
Keiner, beide Wege sind gleichwertig
Die Füllreihenfolge allein macht die Matrizen schon verschieden.
Einer: nur die Füllreihenfolge
Auch das Zentrieren ist in R falsch, und zwar ohne Warnung, weil sechs Elemente ein Vielfaches der drei Spaltenmittel sind.
Umgebung und Werkzeuge
Wozu dient der Staging-Bereich in Git, wenn am Ende ohnehin alles im Commit landet?
Er beschleunigt den Commit
Ein Geschwindigkeitsgewinn ist nicht der Zweck.
Er erlaubt es, aus vielen Änderungen gezielt eine zusammengehörige Auswahl festzuhalten
Richtig. Man wählt aus, was in den nächsten Commit gehört, statt pauschal alles Geänderte einzupacken. So bleiben Commits inhaltlich lesbar.
Er sichert die Dateien gegen Verlust
Gesichert wird erst mit dem Commit, und weitergegeben erst mit dem Push.
Eine Analyse lief vor einem Jahr und bricht heute ab. Welche Massnahme hätte das am ehesten verhindert?
Der Code im Git-Repository
Nötig, aber nicht hinreichend. Der Code ist unverändert; verändert hat sich seine Umgebung.
Eine virtuelle Umgebung mit festgeschriebenen Paketversionen
Richtig. Ohne festgehaltene Versionen ist eine Auswertung nur so lange nachvollziehbar, bis eine Bibliothek ihr Verhalten ändert.
Ein Container
Er löst das Problem ebenfalls und sogar umfassender, ist für diesen Fall aber der grössere Aufwand. Die Umgebung genügt.
Im Dockerfile stehen die Zeilen für den eigenen Code vor denen für die Paketinstallation. Welche Folge hat das?
Bei jeder Codeänderung läuft die gesamte Paketinstallation neu
Richtig. Jede Zeile erzeugt eine zwischengespeicherte Schicht, und eine Änderung macht alle folgenden ungültig. Selten Wechselndes gehört nach oben.
Das Image wird grösser
Die Grösse ändert sich dadurch nicht wesentlich, wohl aber die Bauzeit.
Der Container startet langsamer
Betroffen ist der Bau, nicht der Start.
Über Themen hinweg
Klasse und Instanz, Image und Container, Bauplan und Exemplar. Was verbindet diese Paare?
Es ist dreimal dieselbe Beziehung
Richtig. Eine Klasse beschreibt, wie Objekte aussehen, ein Image, wie Container aussehen. Aus beiden lassen sich beliebig viele gleichartige Exemplare erzeugen, die je eigenen Zustand tragen.
Sie haben nichts miteinander zu tun
Sie stammen aus verschiedenen Themengebieten, folgen aber demselben Muster.
Der Unterschied ist nur die Grösse
Der Unterschied ist die Rolle, nämlich Beschreibung gegenüber laufendem Exemplar.
requirements.txt, renv.lock und ein Dockerfile lösen alle dasselbe Grundproblem. Welches?
Sie beschleunigen die Installation
Ein Nebeneffekt, nicht der Zweck.
Sie machen eine Umgebung wiederherstellbar, statt sie vorauszusetzen
Richtig. Alle drei schreiben fest, was gebraucht wird, damit sich derselbe Zustand anderswo erzeugen lässt. Sie unterscheiden sich nur darin, wie tief sie reichen.
Sie versionieren den Code
Das tut Git. Diese drei beschreiben die Umgebung, in der der Code läuft.
Vektorisierung in NumPy und group_by mit summarise in dplyr wirken sehr verschieden. Was haben sie gemeinsam?
Beide beschreiben, was geschehen soll, und überlassen die Schleife dem Werkzeug
Richtig. Statt Element für Element zu durchlaufen, wird die Operation auf einer ganzen Menge formuliert. Das ist kürzer, schneller und weniger fehleranfällig.
Beide arbeiten nur auf numerischen Daten
group_by arbeitet gerade über kategoriale Schlüssel.
Beide sind Teil derselben Bibliothek
Sie stammen aus verschiedenen Sprachen; gemeinsam ist die Denkweise, nicht die Herkunft.