In dieser Einheit wirst du über das Importieren in Python lernen, Tipps kriegen wie man mit unbekannten Bibliotheken umgeht
und mit dem operator overloading befassen.
Importieren
Bis jetzt haben wir nur über Typen und Funktionen gelernt, die schon in Python eingebaut sind.
Aber einer der besten Sachen über Python (vor allem wenn du ein Datenwissenschaftler bist) ist die unzählige Vielfalt an qualitativen,
selbstgemachten Bibliotheken, die dafür gemacht wurden.
Ein paar von diesen Bibliotheken sind schon ein Bestandteil der "Standard Bibliothek", also bedeutet das, dass du sie überall,
wo du Python laufen lassen kannst hast und andere Bibliotheken kannst du mit Leichtigkeit einfügen,
selbst wenn sie nicht immer mit geliefert werden.
Wie dem auch sei, wir werden diesen auf diesen Code mit Imports zugreifen und wir fangen an in dem wir die math Standard Bibliothek importieren.
import math
print("Es ist Mathematik! Es hat den Typ {}".format(type(math)))
Es ist Mathematik! Es hat den Typ class <'module'>
Math ist ein Modul. Es ist eine Sammlung von Variablen die von einer anderen Person definiert wurden und wir können alle Namen in math sehen in dem wir die eingebaute Funktion dir() verwenden.
Wir können auf diese Variablen zugreifen mit dem dot syntax, ein paar von denen kommen dir vielleicht bekannt vor wie math.pi:
print("pi in 4 Stellen = {:.4}".format(math.pi))
pi in 4 Stellen = 3.142
Aber meistens nutzen wir die vielen Funktionen des Moduls wie math.log
math.log(32, 2)
5.0
Falls wir nicht wissen wie math.log funktioniert können help() anwenden:
help(math.log)
Help on built-in function log in module math:
log(...)
log(x, [base=math.e])
Das Logarithmus von x zur gegebenen Basis als return wert wiedergeben.
Wenn die Basis nicht spezifiziert ist, dann ist der return Wert der Natürlich Logarithmus Basis e von x.
Wir können auch help() an dem gesamten Modul einsetzen, dann würde es uns aber alle Funktionen und Werte Dokumentieren.
Weiterer Import Syntax
Wenn uns sicher sind das wir öfters die Funktionen in math verwenden dann können wir die Kurzversion von der Bibliothek aufschreiben,
in diesem fall ist math schon sehr kurz.
Import math as mt
mt.pi
Du hast vielleicht Code gesehen der das mit populären Bibliotheken wie Pandas, Numpy, Tensorflow oder Matplotlib,
es ist ziemlich weit verbreitet import numpy as np und import pandas as pd zu importieren.
Das as benennt einfach die importierten Module um es ist das gleiche wie wenn man das machen würde:
import math
mt = math
Wäre es nicht toll, wenn wir uns auf alle variablen im Modul an sich oder pi aufrufen könnten statt math.pi oder mt.pi?
Gute Nachricht das können wir.
From math import * print(pi, log(32, 2))
3.141592653589793 5.0
Import * ermöglicht dir das du auch ohne das dot syntax aud die Variablen hinzufügen kannst.
Die schlechte Nachricht ist das es jetzt von den Python Puristen böse blicke gibt und das noch mit gutem Grund.
from math import *
from numpy import *
print(pi, log32, 2))
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/tmp/ipykernel_19/3018510453.py in
1 from math import *
2 from numpy import *
----> 3 print(pi, log(32, 2))
TypeError: return arrays must be of ArrayType
Wieso klappt es jetzt nicht mehr?
Leider führen unsere Stern imports manchmal zu komischen und schwer lösbare debug situationen.
Hier ist das Problem das sowohl math und numpy log als eine andere Funktion haben, aber es wird anders ausgeschrieben.
Weil wir numpy zuletzt importiert haben überschrieb es die Variable von math.
Als Kompromiss kann man nachdem importieren spezifizieren welche teile des Moduls wir wirklich brauchen:
From math import log, pi
From numpy import asarray
Submodule
Manchmal haben Module Variablen, die sich auf andere Module beziehen.
import numpy
print("numpy.random ist ein", type(numpy.random))
print("Es beinhaltet Namen wie…",
dir(numpy.random) [-15:]
)
numpy.random is a <class 'module'>
it contains names such as... ['seed', 'set_state', 'shuffle', 'standard_cauchy', 'standard_exponential',
'standard_gamma', 'standard_normal', 'standard_t', 'test', 'triangular', 'uniform', 'vonmises', 'wald', 'weibull', 'zipf']
Also wenn wir numpy normal importieren und uns auf ein Submodul beziehen möchten, müssen wir 2-mal die Dot Syntax verwenden.
Oh zu orten den du hingehen wirst und oh die Objekte die du sehen wirst
Also nach 6 Einheiten kennst du dich mittlerweile recht gut aus mit ints,
floats, boolen, listen, strings und dictionaries, aber es erweitert sich noch.
Du wirst mit einer Reihe von verschiedenen Bibliotheken arbeiten die alle ihre eigenen Spezialisierungen haben und
dabei wirst du erkennen das sie für alles einen eigenen type haben. Zum Beispiel die matplotlib Bibliothek,
bringt dich in kontakt mit Objekten wo genau definiert wird was Subplots, Figures, TickMarks und Annotations sind.
Pandas Funktionen werden dir DataFrames und Serien geben.
Wir geben dir einen kurzen Survival guide damit du besser mit den komischen neuen Type klar kommst.
Drei Werkzeuge damit wir Komische Objekte besser Verstehen.
In der obere Zeile haben wir eine numpy Funktion namens array gesehen, das haben wir vielleicht in anderen Programmiersprachen gesehen
aber hier sehen wir es zum ersten mal.
Aber diese 3 bekannte und eingebaute Funktionen helfen uns hier weiter:
# Wenn ich jetzt das durchschnittliche vom gewürfeltem haben möchte hilft die mean Methode.
gewürfeltes.mean()
3.1
# Oder vielleicht möchte ich das array zu einer Liste umwandeln, dann muss ich nur die tolist Methode nutzen.
gewürfeltes.tolist()
[4, 2, 4, 5, 3, 1, 4, 2, 5, 1]
Und zuletzt wenn ich im großem und ganzem hilfe brauche nutzen wir help().
# Das ravel Attribut hört sich interessant an, da ich ein großer fan der Klassischen Musik bin.
help(gewürfeltes.ravel)
Help on built-in function ravel:
ravel(...) method of numpy.ndarray instance
a.ravel([order])
Schickt ein flaches array ins return.
Zur vollen Dokumentation beziehen sie sich bitte auf die Dokumentierung in numpy.ndarray.
See Also
--------
numpy.ravel : Equivalenz Funktion
ndarray.flat : a flat iterator on the array.
Von da könntest du jetzt help(gewürfeltes) ausgeben um über das gesamte numpy.ndarray zu lernen
oder du könntest dich hier schlau machen the online docs.
TypeError: can only concatenate list (not "int") to list
Naja, dumme frage es ist ein Fehler, aber was wäre wenn...
Gewürfeltes + 10
Aha, da haben wir es. Wenn ein neuer Typ definiert wird, muss auch definiert werden wie es mit +, -, *, :, <,… interagiert.
Der Macher von numpy arrays erlaubt, dass die addierte Zahl mit jeder stelle des arrays addiert wird.
Wir zeigen jetzt ein paar Interaktionen mit numpy und Python Operanten vor damit man sich besser was darunter vorstellen kann.
# An welchen Stellen ist der Wert des Würfels weniger gleich zu 3?
Gewürfeltes <= 3
array([False, True, False, False, True, True, False, True, False, True])
# Nimm die letzte Stelle der zweiten Reihe
x[1,-1]
6
# Nimm die letzte Stelle aus der zweiten Subliste aus unserer genesteten Liste.
xlist[1,-1]
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/tmp/ipykernel_19/3020169379.py in <module>
1 # Get the last element of the second sublist of our nested list?
----> 2 xlist[1,-1]
TypeError: list indices must be integers or slices, not tuple
Der Numpy ndarrays Typ ist zur Arbeit mit multidimensionaler Daten spezialisiert und hat daher seine eigen Logik zur Indexierung definiert,
daher können wir es über einen tuple indexieren in jeder Dimension.
Wann ergibt 1 + 1 nicht mehr 2?
Vielleicht hast du schon von tensorflow gehört oder es mal verwendet, es ist eine Python Bibliothek die meistens für Deep Learning genutzt wird und es nutzt das Operator Overloading gut aus.
Import tensorflow as tf
# Erstelle zwei Konstante, die jeweils den Wert von 1 haben.
a = tf.constant(1)
b = tf.constant(1)
# Wenn du sie addierst kriegst du…
a + b
KMP_ABORT_DELAY=0
KMP_ADAPTIVE_LOCK_PROPS='1,1024'
KMP_ALIGN_ALLOC=64
KMP_ALL_THREADPRIVATE=128
KMP_ATOMIC_MODE=2
KMP_BLOCKTIME=0
KMP_CPUINFO_FILE: value is not defined
KMP_DETERMINISTIC_REDUCTION=false
KMP_DEVICE_THREAD_LIMIT=2147483647
KMP_DISP_NUM_BUFFERS=7
KMP_DUPLICATE_LIB_OK=false
KMP_ENABLE_TASK_THROTTLING=true
KMP_FORCE_REDUCTION: value is not defined
KMP_FOREIGN_THREADS_THREADPRIVATE=true
KMP_FORKJOIN_BARRIER='2,2'
KMP_FORKJOIN_BARRIER_PATTERN='hyper,hyper'
KMP_GTID_MODE=3
KMP_HANDLE_SIGNALS=false
KMP_HOT_TEAMS_MAX_LEVEL=1
KMP_HOT_TEAMS_MODE=0
KMP_INIT_AT_FORK=true
KMP_LIBRARY=throughput
KMP_LOCK_KIND=queuing
KMP_MALLOC_POOL_INCR=1M
KMP_NUM_LOCKS_IN_BLOCK=1
KMP_PLAIN_BARRIER='2,2'
KMP_PLAIN_BARRIER_PATTERN='hyper,hyper'
KMP_REDUCTION_BARRIER='1,1'
KMP_REDUCTION_BARRIER_PATTERN='hyper,hyper'
KMP_SCHEDULE='static,balanced;guided,iterative'
KMP_SETTINGS=true
KMP_SPIN_BACKOFF_PARAMS='4096,100'
KMP_STACKOFFSET=64
KMP_STACKPAD=0
KMP_STACKSIZE=8M
KMP_STORAGE_MAP=false
KMP_TASKING=2
KMP_TASKLOOP_MIN_TASKS=0
KMP_TASK_STEALING_CONSTRAINT=1
KMP_TEAMS_THREAD_LIMIT=4
KMP_TOPOLOGY_METHOD=all
KMP_USE_YIELD=1
KMP_VERSION=false
KMP_WARNINGS=false
OMP_AFFINITY_FORMAT='OMP: pid %P tid %i thread %n bound to OS proc set {%A}'
OMP_ALLOCATOR=omp_default_mem_alloc
OMP_CANCELLATION=false
OMP_DEFAULT_DEVICE=0
OMP_DISPLAY_AFFINITY=false
OMP_DISPLAY_ENV=false
OMP_DYNAMIC=false
OMP_MAX_ACTIVE_LEVELS=1
OMP_MAX_TASK_PRIORITY=0
OMP_NESTED: deprecated; max-active-levels-var=1
OMP_NUM_THREADS: value is not defined
OMP_PLACES: value is not defined
OMP_PROC_BIND='intel'
OMP_SCHEDULE='static'
OMP_STACKSIZE=8M
OMP_TARGET_OFFLOAD=DEFAULT
OMP_THREAD_LIMIT=2147483647
OMP_WAIT_POLICY=PASSIVE
KMP_AFFINITY='verbose,warnings,respect,granularity=fine,compact,1,0'
2021-11-11 14:28:36.299104: I tensorflow/core/common_runtime/process_util.cc:146] Creating new thread pool with default inter op setting: 2. Tune using inter_op_parallelism_threads for best performance.
<tf.Tensor: shape=(), dtype=int32, numpy=2>
Laut TensorFlow ist a + b nicht 2, sondern ein Symbolisches Handle zu einer der Outputs einer Operation.
Es hat nicht den wert des Outputs der Operanten, aber stellt eine Methode zur Verfügung um diese in einer TenserFlow tf.session zu kontrollieren.
Was davon mitnehmen sollte ist, dass solche Sachen dank Bibliotheken möglich ist und das Bibliotheken öfters Operator Overloading nutzen um einfach
und nahezu magisch wirkende Lösungen zu erreichen.
Nur weil du verstehst wie die Operanten normalerweise Funktionieren, heißt es noch lange nicht das du gleich verstehen musst wie es mit anderen Typen,
Funktionen oder Variablen interagiert.
Nachdem du dich ein wenig an die DataFrames gewohnt hast wird es dir viel leichter fallen mit ihnen zu arbeiten, vielleicht hilft dir dieses Beispiel:
# Hol dir die reihen, wo die Population über eine Million reicht und Süd Amerika ist
# Get the rows with population over 1m in South America
df[(df['population'] > 10**6) & (df['continent'] == 'South America')]
Aber wieso Funktioniert es? Die oberen Beispiele zeigen 5 verschiedene Overloaded Operators.
Was machen die alle? Es ist schon sehr hilfreich die Antworten dazu zu wissen wenn es zu Fehlern kommt.
Würdest du gerne mehr darüber wissen?
Hast du jemals beim help() oder bei dir() dich je gewundert was all diese komischen namen mit den untenliegenden Strichen sind?
Es hat direkt was mit Operator Overloading zu tun.
Wenn ein Python Programmierer definieren will, wie Operanten mit ihren Typen interagieren soll implementieren sie Methoden mit speziellen Namen,
die mit zwei unterstrichen anfängt und endet. __lt__, __setattr__ oder __contains__ wären genau solche Methoden.
Normalerweise haben Namen mit zwei unterstrichen eine wichtige Bedeutung.
Variable x auf [1, 2, 3] tut tatsächlich die Liste mit der Methode __contains__ aufrufen, das passiert ohne das der Mensch das mitbekommen muss,
sonst müsste er das hier anschauen, [1, 2, 3].__contains__(x).
Wenn es dich interessiert, könntest du mehr auf Python's official documentation darüber lernen,
hier stehen viele spezielle unterstrichene Methoden und sie werden auch gut erklärt.
Wir werden in dieser Einheit nicht mehr unsere eigenen Typen definieren können und ich hoffe das wir dich schon bald wieder im nächsten Kurs sehen.