Kap. 5+6 aktualisiert, Kap 6.1, 6.2, 7 hinzugefügt

Kapitel 6.1, 6.2 und 7 aus der englischen Version übernommen.
Kapitel 5 und 6 getauscht, um der englischen Version zu entsprechen. 
Texte der Kapitel 5 und 6 Kapitel um fehlende Teile erweitert.
This commit is contained in:
Rakasch 2019-04-06 20:18:14 +02:00 committed by GitHub
parent 2dde374091
commit c0c2272be0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -386,58 +386,9 @@ filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7]
[add_10(i) for i in [1, 2, 3]] #=> [11, 12, 13]
[x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7]
####################################################
## 5. Klassen
####################################################
# Wir bilden die Unterklasse eines Objekts, um Klassen zu erhalten.
class Human(object):
# Ein Klassenattribut. Es wird von allen Instanzen einer Klasse geteilt
species = "H. sapiens"
# Ein simpler Konstruktor
def __init__(self, name):
# Wir weisen das Argument name dem name-Attribut der Instanz zu
self.name = name
# Eine Instanzmethode. Alle Methoden erhalten self als erstes Argument.
def say(self, msg):
return "%s: %s" % (self.name, msg)
# Eine Klassenmethode wird von allen Instanzen geteilt.
# Sie werden mit der aufrufenden Klasse als erstem Argument aufgerufen
@classmethod
def get_species(cls):
return cls.species
# Eine statische Methode wird ohne Klasse oder Instanz aufgerufen
@staticmethod
def grunt():
return "*grunt*"
# Eine Instanz einer Klasse erstellen
i = Human(name="Ian")
print i.say("hi") # gibt "Ian: hi" aus
j = Human("Joel")
print j.say("hello") #gibt "Joel: hello" aus
# Rufen wir mal unsere Klassenmethode auf
i.get_species() #=> "H. sapiens"
# Ändern wir mal das gemeinsame Attribut
Human.species = "H. neanderthalensis"
i.get_species() #=> "H. neanderthalensis"
j.get_species() #=> "H. neanderthalensis"
# Aufruf der statischen Methode
Human.grunt() #=> "*grunt*"
####################################################
## 6. Module
## 5. Module
####################################################
# Wir können Module importieren
@ -461,11 +412,339 @@ math.sqrt(16) == m.sqrt(16) #=> True
# können unsere eigenen schreiben und importieren. Der Name des
# Moduls ist der Dateiname.
# Wir können auch die Funktionen und Attribute eines
# Moduls herausfinden.
# Wir können herausfinden, welche Funktionen und Attribute in einem
# Modul definiert sind.
import math
dir(math)
# Wenn Sie ein Python-Skript namens math.py im selben Ordner
# wie Ihr aktuelles Skript haben, wird die Datei math.py
# anstelle des integrierten Python-Moduls geladen.
# Dies geschieht, weil der lokale Ordner Vorrang
# vor den in Python integrierten Bibliotheken hat.
####################################################
## 6. Klassen
####################################################
# Wir verwenden das Schlüsselwort "class" um eine Klasse zu erzeugen.
class Human(object):
# Ein Klassenattribut. Es wird von allen Instanzen einer Klasse geteilt
species = "H. sapiens"
# Ein simpler Konstruktor, wird aufgerufen, wenn diese Klasse instanziiert wird.
# Beachten Sie, dass die doppelten vorangestellten und nachgestellten
# Unterstriche Objekte oder Attribute bezeichnen, die von Python verwendet werden,
# aber in benutzergesteuerten Namespaces leben.
# Methoden (oder Objekte oder Attribute) wie: __init__, __str__, __repr__ usw.
# werden als Sondermethoden (oder manchmal als Dundermethoden bezeichnet) bezeichnet.
# Sie sollten solche Namen nicht selbst erfinden.
def __init__(self, name):
# Wir weisen das Argument name dem name-Attribut der Instanz zu
self.name = name
# Eine Instanzmethode. Alle Methoden erhalten "self" als erstes Argument.
def say(self, msg):
return "%s: %s" % (self.name, msg)
# Eine weitere Instanzmethode
def sing(self):
return 'yo... yo... microphone check... one two... one two...'
# Eine Klassenmethode wird von allen Instanzen geteilt.
# Sie werden mit der aufrufenden Klasse als erstem Argument aufgerufen
@classmethod
def get_species(cls):
return cls.species
# Eine statische Methode wird ohne Klasse oder Instanz aufgerufen
@staticmethod
def grunt():
return "*grunt*"
# Eine Eigenschaft (Property) ist wie ein Getter.
    # Es verwandelt die Methode age() in ein schreibgeschütztes Attribut mit demselben Namen.
    # Es ist jedoch nicht nötig, triviale Getter und Setter in Python zu schreiben.
@property
def age(self):
return self._age
    # Damit kann die Eigenschaft festgelegt werden
@age.setter
def age(self, age):
self._age = age
    # Damit kann die Eigenschaft gelöscht werden
@age.deleter
def age(self):
del self._age
# Wenn ein Python-Interpreter eine Quelldatei liest, führt er den gesamten Code aus.
# Diese __name__-Prüfung stellt sicher, dass dieser Codeblock nur ausgeführt wird,
# wenn dieses Modul das Hauptprogramm ist.
if __name__ == '__main__':
# Eine Instanz einer Klasse erstellen
i = Human(name="Ian")
i.say("hi") # "Ian: hi"
j = Human("Joel")
j.say("hello") # "Joel: hello"
# i und j sind Instanzen des Typs Mensch, oder anders ausgedrückt: Sie sind Objekte des Menschen
# Rufen wir unsere Klassenmethode auf
i.say(i.get_species()) # "Ian: H. sapiens"
# Ändern wir das gemeinsame Attribut
Human.species = "H. neanderthalensis"
i.say(i.get_species()) # => "Ian: H. neanderthalensis"
j.say(j.get_species()) # => "Joel: H. neanderthalensis"
# Aufruf der statischen Methode
print(Human.grunt()) # => "*grunt*"
# Kann keine statische Methode mit Instanz des Objekts aufrufen,
# da i.grunt () automatisch "self" (das Objekt i) als Argument verwendet
print(i.grunt()) # => TypeError: grunt() takes 0 positional arguments but 1 was given
# Die Eigenschaft für diese Instanz aktualisieren
i.age = 42
# die Eigenschaft auslesen
i.say(i.age) # => "Ian: 42"
j.say(j.age) # => "Joel: 0"
# die Eigenschaft löschen
del i.age
# i.age # => würde einen AttributeError werfen
####################################################
## 6.1 Inheritance
####################################################
# Vererbung ermöglicht die Definition neuer untergeordneter Klassen,
# die Methoden und Variablen von ihrer übergeordneten Klasse erben.
# Wenn Sie die oben definierte Human-Klasse als Basis- oder Elternklasse verwenden,
# können Sie eine untergeordnete Klasse, Superhero, definieren, die die Klassenvariablen
# wie "species", "name" und "age" sowie Methoden wie "sing" und "grunzen" aus der Klasse Human erbt.
# Die Untergeordnete Klasse kann aber auch eigene Eigenschaften haben.
# Um von der Modularisierung per Datei zu profitieren, können Sie die Klassen
# in ihren eigenen Dateien platzieren, z. B. human.py
# Um Funktionen aus anderen Dateien zu importieren, verwenden Sie das folgende Format
# from "Dateiname-ohne-Erweiterung" impotr "Funktion-oder-Klasse"
from human import Human
# Geben Sie die übergeordnete(n) Klasse(n) als Parameter für die Klassendefinition an
class Superhero(Human):
# Wenn die untergeordnete Klasse alle Definitionen des übergeordneten Elements
# ohne Änderungen erben soll, können Sie einfach das Schlüsselwort "pass"
# (und nichts anderes) verwenden. In diesem Fall wird jedoch auskommentiert,
# um eine eindeutige untergeordnete Klasse zuzulassen:
# pass
# Kindklassen können die Attribute ihrer Eltern überschreiben
species = 'Superhuman'
# Kinder erben automatisch den Konstruktor ihrer übergeordneten Klasse
# einschließlich ihrer Argumente, können aber auch zusätzliche Argumente oder
# Definitionen definieren und ihre Methoden zB den Klassenkonstruktor überschreiben.
# Dieser Konstruktor erbt das Argument "name" von der Klasse "Human" und
# fügt die Argumente "superpowers" und "movie" hinzu:
def __init__(self, name, movie=False,
superpowers=["super strength", "bulletproofing"]):
# zusätzliche Klassenattribute hinzufügen:
self.fictional = True
self.movie = movie
# Beachten Sie die veränderlichen Standardwerte, da die Standardwerte gemeinsam genutzt werden
self.superpowers = superpowers
# Mit der Funktion "super" können Sie auf die Methoden der übergeordneten Klasse
# zugreifen, die vom untergeordneten Objekt überschrieben werden,
# in diesem Fall die Methode __init__.
        # Dies ruft den Konstruktor der übergeordneten Klasse auf:
super().__init__(name)
# überschreiben der "sing" Methode
def sing(self):
return 'Dun, dun, DUN!'
# eine zusätzliche Instanzmethode hinzufügen
def boast(self):
for power in self.superpowers:
print("I wield the power of {pow}!".format(pow=power))
if __name__ == '__main__':
sup = Superhero(name="Tick")
# Instanztypprüfungen
if isinstance(sup, Human):
print('I am human')
if type(sup) is Superhero:
print('I am a superhero')
# Die Reihenfolge der Methodenauflösung (MRO = Method Resolution Order) anzeigen, die sowohl von getattr() als auch von super() verwendet wird.
    # Dieses Attribut ist dynamisch und kann aktualisiert werden.
print(Superhero.__mro__) # => (<class '__main__.Superhero'>,
# => <class 'human.Human'>, <class 'object'>)
# Ruft die übergeordnete Methode auf, verwendet jedoch das eigene Klassenattribut
print(sup.get_species()) # => Superhuman
# Ruft die überschriebene Methode auf
print(sup.sing()) # => Dun, dun, DUN!
# Ruft die Methode von Human auf
sup.say('Spoon') # => Tick: Spoon
# Aufruf einer Methode, die nur in Superhero existiert
sup.boast() # => I wield the power of super strength!
# => I wield the power of bulletproofing!
# Vererbtes Klassenattribut
sup.age = 31
print(sup.age) # => 31
# Attribut, das nur in Superhero existiert
print('Am I Oscar eligible? ' + str(sup.movie))
####################################################
## 6.2 Multiple Inheritance
####################################################
# Eine weitere Klassendefinition
# bat.py
class Bat:
species = 'Baty'
def __init__(self, can_fly=True):
self.fly = can_fly
# This class also has a say method
def say(self, msg):
msg = '... ... ...'
return msg
# And its own method as well
def sonar(self):
return '))) ... ((('
if __name__ == '__main__':
b = Bat()
print(b.say('hello'))
print(b.fly)
# Und noch eine andere Klassendefinition, die von Superhero und Bat erbt
# superhero.py
from superhero import Superhero
from bat import Bat
# Definieren Sie Batman als eine Kindklasse, das von Superheld und Bat erbt
class Batman(Superhero, Bat):
def __init__(self, *args, **kwargs):
# In der Regel müssen Sie super aufrufen, um Attribute zu erben:
# super (Batman, selbst) .__ init__ (* args, ** kwargs)
# Allerdings handelt es sich hier um Mehrfachvererbung, und super()
# funktioniert nur mit der nächsten Basisklasse in der MRO-Liste.
# Stattdessen rufen wir explizit __init__ für alle Vorfahren auf.
# Die Verwendung von *args und **kwargs ermöglicht die saubere Übergabe von
# Argumenten, wobei jedes übergeordnete Element eine Schicht der Zwiebel "abschält".
Superhero.__init__(self, 'anonymous', movie=True,
superpowers=['Wealthy'], *args, **kwargs)
Bat.__init__(self, *args, can_fly=False, **kwargs)
# überschreibt den Wert für das Namensattribut
self.name = 'Sad Affleck'
def sing(self):
return 'nan nan nan nan nan batman!'
if __name__ == '__main__':
sup = Batman()
# Die Reihenfolge der Methodenauflösung (MRO = Method Resolution Order) anzeigen,
# die sowohl von getattr() als auch von super() verwendet wird.
# Dieses Attribut ist dynamisch und kann aktualisiert werden.
print(Batman.__mro__) # => (<class '__main__.Batman'>,
# => <class 'superhero.Superhero'>,
# => <class 'human.Human'>,
# => <class 'bat.Bat'>, <class 'object'>)
# Ruft die übergeordnete Methode auf, verwendet jedoch das eigene Klassenattribut
print(sup.get_species()) # => Superhuman
# Ruft die überschriebene Methode auf
print(sup.sing()) # => nan nan nan nan nan batman!
# Ruft die Methode von Human auf, weil die Reihenfolge der Vererbung wichtig ist
sup.say('I agree') # => Sad Affleck: I agree
# Aufrufmethode, die nur im 2. Vorfahren existiert
print(sup.sonar()) # => ))) ... (((
# Vererbtes Klassenattribut
sup.age = 100
print(sup.age) # => 100
# Vererbtes Attribut vom 2. Vorfahren, dessen Standardwert überschrieben wurde.
print('Can I fly? ' + str(sup.fly)) # => Can I fly? False
####################################################
## 7. Fortgeschrittenes
####################################################
# Generatoren helfen Ihnen, lazy Code zu erstellen.
def double_numbers(iterable):
for i in iterable:
yield i + i
# Generatoren sind speichereffizient, da sie nur die Daten laden,
# die zur Verarbeitung des nächsten Werts in der iterierbaren Komponente
# erforderlich sind. Dadurch können sie ansonsten unzulässig große Wertebereiche ausführen.
# HINWEIS: `range` ersetzt` xrange` in Python 3.
for i in double_numbers(range(1, 900000000)): # `range` ist ein Generator.
print(i)
if i >= 30:
break
# Genauso wie Sie ein 'list comprehension' (Listen Abstraktion) erstellen können, können Sie auch 'generator comprehension' (Generator Abstraktion) erstellen.
values = (-x for x in [1,2,3,4,5])
for x in values:
print(x) # prints -1 -2 -3 -4 -5 to console/terminal
# Sie können eine Generator Abstraktion auch direkt in eine Liste umwandeln (casten).
values = (-x for x in [1,2,3,4,5])
gen_to_list = list(values)
print(gen_to_list) # => [-1, -2, -3, -4, -5]
# Decorators
# In diesem Beispiel umschliesst "beg" "say". Wenn say_please True ist, wird die zurückgegebene Nachricht geändert.
from functools import wraps
def beg(target_function):
@wraps(target_function)
def wrapper(*args, **kwargs):
msg, say_please = target_function(*args, **kwargs)
if say_please:
return "{} {}".format(msg, "Please! I am poor :(")
return msg
return wrapper
@beg
def say(say_please=False):
msg = "Can you buy me a beer?"
return msg, say_please
print(say()) # Can you buy me a beer?
print(say(say_please=True)) # Can you buy me a beer? Please! I am poor :(
```