summaryrefslogtreecommitdiffhomepage
path: root/de-de
diff options
context:
space:
mode:
Diffstat (limited to 'de-de')
-rw-r--r--de-de/asciidoc-de.html.markdown6
-rw-r--r--de-de/c++-de.html.markdown1157
-rw-r--r--de-de/python-de.html.markdown359
3 files changed, 1479 insertions, 43 deletions
diff --git a/de-de/asciidoc-de.html.markdown b/de-de/asciidoc-de.html.markdown
index 24100e0b..e3f64a00 100644
--- a/de-de/asciidoc-de.html.markdown
+++ b/de-de/asciidoc-de.html.markdown
@@ -88,7 +88,7 @@ Abteilungstitel
Listen
-Um eine Aufzählung zu erstellen verwendest du Sternchen.
+Um eine Aufzählung zu erstellen, verwendest du Sternchen.
```
* foo
@@ -96,7 +96,7 @@ Um eine Aufzählung zu erstellen verwendest du Sternchen.
* baz
```
-Um eine nummerierte Liste zu erstellen verwendest du Punkte.
+Um eine nummerierte Liste zu erstellen, verwendest du Punkte.
```
. item 1
@@ -104,7 +104,7 @@ Um eine nummerierte Liste zu erstellen verwendest du Punkte.
. item 3
```
-Um Listen zu verschachteln musst du zusätzliche Sternchen beziehungsweise Punkte hinzufügen. Dies ist bis zu fünf Mal möglich.
+Um Listen zu verschachteln, musst du zusätzliche Sternchen beziehungsweise Punkte hinzufügen. Dies ist bis zu fünf Mal möglich.
```
* foo 1
diff --git a/de-de/c++-de.html.markdown b/de-de/c++-de.html.markdown
new file mode 100644
index 00000000..cef7514b
--- /dev/null
+++ b/de-de/c++-de.html.markdown
@@ -0,0 +1,1157 @@
+---
+language: c++
+filename: learncpp-de.cpp
+contributors:
+ - ["Steven Basart", "http://github.com/xksteven"]
+ - ["Matt Kline", "https://github.com/mrkline"]
+ - ["Geoff Liu", "http://geoffliu.me"]
+ - ["Connor Waters", "http://github.com/connorwaters"]
+ - ["Ankush Goyal", "http://github.com/ankushg07"]
+ - ["Jatin Dhankhar", "https://github.com/jatindhankhar"]
+ - ["Maximilian Sonnenburg", "https://github.com/LamdaLamdaLamda"]
+lang: de-de
+---
+
+C++ ist eine Systemprogrammiersprache die,
+
+[laut dem Begründer Bjarne Stroustrup](http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2014/Keynote)
+entworfen wurde um,
+
+- "besseres C" zu sein
+- Datenabstraktion zu unterstützen
+- Objektorientierung zu unterstützen
+- generische Programmierung zu unterstützen
+
+Durch seinen Syntax kann sie durchaus schwieriger und komplexer als neuere Sprachen sein.
+
+Sie ist weit verbreitet, weil sie in Maschinen-Code kompiliert, welches direkt vom Prozessor ausgeführt
+werden kann und somit eine strikte Kontrolle über die Hardware bietet und gleichzeitig
+High-Level-Features wie generics, exceptions und Klassen enthält.
+
+Diese Kombination aus Geschwindigkeit und Funktionalität bildet C++ und ist eine der
+weitverbreitesten Programmiersprachen.
+
+```c++
+//////////////////
+// Vergleich zu C
+//////////////////
+
+// C ist fast eine Untermenge von C++ und teilt sich grundsätzlich den
+// Syntax für Variablen Deklarationen, primitiven Typen und Funktionen.
+
+// Wie in C ist der Programmeinsprungpunkt eine Funktion, welche "main" genannt wird und
+// einen Integer als Rückgabetyp besitzt.
+
+// Dieser Wert fungiert als Beendigungsstatus des Programms.
+// Siehe: https://de.wikipedia.org/wiki/Return_Code für weitere Informationen
+int main(int argc, char** argv)
+{
+ // Kommandozeilen Argumente werden genauso wie in C über argc und argv übergeben
+ // argc entspricht der Anzahl von Argumenten und argv ist ein Array von C-style
+ // strings (char*), welche die Argumente repräsentieren.
+ // Das erste Argument ist der Name des Programms, welches aufgerufen wird.
+ // Argc und argv können, wenn nicht benötigt, weg gelassen werden, indem
+ // die Funktionssignatur "int main()" verwendet wird.
+
+ // Ein Rückgabewert von 0 repräsentiert die erfolgreiche Ausführung.
+ return 0;
+}
+
+// C++ unterscheidet sich in einigen Punkten von C:
+
+// In C++ sind Zeichen-Literale char´s
+sizeof('c') == sizeof(char) == 1
+
+// In C sind Zeichen-Literale int´s
+sizeof('c') == sizeof(int)
+
+// C++ verwendet striktes prototyping
+void func(); // Funktion ohne Argumente
+
+// In C
+void func(); // Funktion mit beliebiger Anzahl von Argumenten
+
+// Verwende nullptr, anstatt von NULL!!!
+int* ip = nullptr;
+
+// C standard header sind in C++ verfügbar.
+// C header enden mit .h, während
+// C++ header das Präfix "c" besitzen und kein ".h" Suffix verwenden.
+
+// Die C++ Standard Version:
+#include <cstdio>
+
+// Die C Standard Version:
+#include <stdio.h>
+
+int main()
+{
+ printf("Hello, world!\n");
+ return 0;
+}
+
+///////////////////////
+// Funktionsüberladung
+///////////////////////
+
+// C++ unterstützt Funktionsüberladung
+// Jede Funktion kann unterschiedliche Parameter erhalten.
+void print(char const* myString)
+{
+ printf("String %s\n", myString);
+}
+
+void print(int myInt)
+{
+ printf("My int is %d", myInt);
+}
+
+int main()
+{
+ print("Hello"); // Wird aufgelöst zu "void print(const char*)"
+ print(15); // Wird aufgelöst zu "void print(int)"
+}
+
+/////////////////////////////
+// Standard Funktionsargumente
+/////////////////////////////
+
+// Argumente können per Standard für eine Funktion gesetzt werden,
+// wenn diese beim Aufruf nicht bereitgestellt werden.
+void doSomethingWithInts(int a = 1, int b = 4)
+{
+ // führe Anweisungen mit "int´s" aus.
+}
+
+int main()
+{
+ doSomethingWithInts(); // a = 1, b = 4
+ doSomethingWithInts(20); // a = 20, b = 4
+ doSomethingWithInts(20, 5); // a = 20, b = 5
+}
+
+// Standard-Argumente müssen am Ende der Liste der Argumente stehen.
+void invalidDeclaration(int a = 1, int b) // Fehler!
+{
+}
+
+
+/////////////
+// Namespaces (Namesräume)
+/////////////
+
+// Namespaces stellen einen getrennten Gültigkeitsbereich für Variablen,
+// Funktionen und andere Deklarationen zur Verfügung.
+// Namespaces können geschachtelt werden.
+namespace First
+{
+ namespace Nested
+ {
+ void foo()
+ {
+ printf("This is First::Nested::foo\n");
+ }
+ } // Ende des Namespace "Nested"
+} // Ende des Namespace "First"
+
+namespace Second
+{
+ void foo()
+ {
+ printf("This is Second::foo\n");
+ }
+}
+
+void foo()
+{
+ printf("This is global foo\n");
+}
+
+int main()
+{
+ // Fügt all Symbole aus dem namespace Second in den aktuellen Gültigkeitsbereich (scope).
+ // "foo()" wird nun nicht länger funktionieren, da es nun doppeldeutig ist, ob foo aus
+ // dem namespace foo oder darüberliegenden aufgerufen wird.
+ using namespace Second;
+
+ Second::foo(); // Gibt "This is Second::foo" aus.
+ First::Nested::foo(); // Gibt "This is First::Nested::foo" aus.
+ ::foo(); // Gibt "This is global foo" aus.
+}
+
+///////////////
+// Eingabe/Ausgabe
+///////////////
+
+// C++ verwendet für die Eingabe und Ausgabe streams.
+// cin, cout und cerr repräsentieren stdin, stdout und stderr.
+// << ist der Einfügeoperator und >> ist der Extraktionsoperator.
+
+#include <iostream> // Include für Eingabe/Ausgabe (I/O) streams
+
+using namespace std; // Streams befinden sich im std namespace (standard library)
+
+int main()
+{
+ int myInt;
+
+ // Ausgabe auf stdout (oder Terminal/Bildschirm)
+ cout << "Enter your favorite number:\n";
+
+ // Empfängt Eingabe
+ cin >> myInt;
+
+ // cout kann ebenfalls formatiert werden
+ cout << "Your favorite number is " << myInt << "\n";
+ // Gibt "Your favorite number is <myInt>" aus
+
+ cerr << "Used for error messages";
+}
+
+//////////
+// Zeichenketten (Strings)
+//////////
+
+// Strings in C++ sind Objekte und haben diverse member-functions
+#include <string>
+
+using namespace std; // Strings sind ebenfalls im namespace std (Standard Bibliothek)
+
+string myString = "Hello";
+string myOtherString = " World";
+
+// + wird für das Anhängen von strings verwendet.
+cout << myString + myOtherString; // "Hello World"
+
+cout << myString + " You"; // "Hello You"
+
+// C++ strings sind mutable.
+myString.append(" Dog");
+cout << myString; // "Hello Dog"
+
+
+/////////////
+// Referenzen
+/////////////
+
+// Zusätzlich zu Pointern, wie jene in C.
+// C++ besitzt _Referenzen_.
+// Diese sind Pointer-Typen, welche nicht erneut zugewiesen werden können
+// und nicht Null sein können.
+// Sie besitzen den selben Syntax wie Variablen.
+// Für die Dereferenzierung ist kein * notwendig und
+// & (die Adresse) wird nicht für die Zuweisung verwendet.
+
+using namespace std;
+
+string foo = "I am foo";
+string bar = "I am bar";
+
+
+string& fooRef = foo; // Erzeugt eine Referenz auf foo.
+fooRef += ". Hi!"; // Verändert foo durch die Referenz
+cout << fooRef; // Gibt "I am foo. Hi!" aus.
+
+
+// Weist "fooRef" nicht erneut zu. Dies ist dasselbe, wie "foo = bar" und
+// foo == "I am bar"
+// nach dieser Zeile
+cout << &fooRef << endl; // Gibt die Adresse von foo aus
+fooRef = bar;
+cout << &fooRef << endl; // Gibt ebenfalls die Adresse von foo aus
+cout << fooRef; // Gibt "I am bar" aus
+
+// Die Adresse von fooRef verbleibt die selbe, sie verweist immer noch auf foo
+
+const string& barRef = bar; // Erzeugt konstante Referenz auf bar.
+// Wie in C, können konstante Werte ( und Pointer bzw. Referenzen) nicht verändert werden.
+
+barRef += ". Hi!"; // Fehler: konstante Referenzen können nicht verändert werden.
+
+// Hinweis: bevor wir genauer Referenzen besprechen, schauen wir uns zuerst ein Konzept an,
+// welches als "temporäres Objekt" bezeichnet wird. Gehen wir von folgenden Code aus:
+string tempObjectFun() { ... }
+string retVal = tempObjectFun();
+
+// Was passiert nun in der zweiten Zeile:
+// - ein String Objekt wird von "tempObjectFun" zurückgegeben
+// - ein neuer String wird mit dem zurückgegebenen Objekt als Argument für den Konstruktor erzeugt.
+// - das zurückgegebene Objekt wird zerstört
+// Das zurückgegbene Objekt wird temporäres Objekt genannt. Temporäre Objekte werden erzeugt
+// wann immer eine Funktion ein Objekt zurückgibt. Zerstört werden diese am Ende der Auswertung des Ausdrucks
+// (dies schreibt der Standard vor, aber Compiler sind berechtigt dieses Verhalten zu ändern. Siehe "return value optimization"
+// für Details). Wie in diesem Code:
+foo(bar(tempObjectFun()))
+
+// Nehmen wir an foo und bar existieren. Das Objekt wird von "tempObjectFun" zurückgegeben,
+// wird an bar übergeben und ist zerstört bevor foo aufgerufen wird.
+
+// Zurück zu Referenzen. Die Annahme, dass die "am Ende des Ausdrucks" Regel gültig ist,
+// wenn das temporäre Objekt an eine konstante Referenz gebunden ist, ist der Fall, wenn die Lebensdauer
+// auf den aktuellen Gültigkeitsbereich erweitert wird.
+
+void constReferenceTempObjectFun() {
+ // constRef erhält das temporäre Objekt und ist gültig bis ans Ende der Funktion
+ const string& constRef = tempObjectFun();
+ ...
+}
+
+// Eine andere Art von Referenzen wurde in C++11 eingeführt und ist speziell für
+// temporäre Objekte. Es ist nicht möglich Variablen des Typs zu besitzen, aber
+// Vorrechte bei der Auflösung zu besitzen.
+
+void someFun(string& s) { ... } // Reguläre Referenz
+void someFun(string&& s) { ... } // Referenz auf ein temporäres Objekt
+
+string foo;
+someFun(foo); // Ruft die Funktion mit der regulären Referenz auf
+someFun(tempObjectFun()); // Ruft die Funktion mit der temporären Referenz auf
+
+// Zum Beispiel existieren diese zwei Varianten von Konstruktoren für
+// std::basic_string:
+basic_string(const basic_string& other);
+basic_string(basic_string&& other);
+
+// Nehmen wir an, wir erzeugen einen neuen String eines temporären Objekts (welches später
+// zerstört wird), hierbei existiert ein effizienterer Konstruktor. Dieses Konzept wird
+// als "move semantics" bezeichnet (bewegen eines Objekts in ein anderes in C++).
+
+/////////////////////
+// Enumerations (Aufzählungstypen)
+/////////////////////
+
+// Enums sind eine einfachere Art und Weise einen Wert einer Konstante zu zuweisen.
+// Häufig wird dies verwendet, um den Code lesbarer zu gestalten bzw. zu visualisieren.
+enum ECarTypes
+{
+ Sedan,
+ Hatchback,
+ SUV,
+ Wagon
+};
+
+ECarTypes GetPreferredCarType()
+{
+ return ECarTypes::Hatchback;
+}
+
+// Mit C++11 existiert eine einfache Möglichkeit einem Typ dem Enum zu zuweisen. Dies
+// kann durchaus sinnvoll bei der Serialisierung von Daten sein, oder bei der Konvertierung
+// zwischen Typen bzw. Konstanten.
+enum ECarTypes : uint8_t
+{
+ Sedan, // 0
+ Hatchback, // 1
+ SUV = 254, // 254
+ Hybrid // 255
+};
+
+void WriteByteToFile(uint8_t InputValue)
+{
+ // Serialisierung von "InputValue" in eine Datei
+}
+
+void WritePreferredCarTypeToFile(ECarTypes InputCarType)
+{
+ // Das enum wird implizit zu einem "uint8_t" konvertiert. Bedingt dadurch, dass
+ // es sich um ein "enum" handelt.
+ WriteByteToFile(InputCarType);
+}
+
+// Nicht immer ist es gewünscht, dass enum´s zu einem Integer oder zu einem anderen
+// enum umgewandelt werden. Daher ist es möglich eine enum-Klasse zu erzeugen, welche
+// nicht implizit umgewandelt wird.
+enum class ECarTypes : uint8_t
+{
+ Sedan, // 0
+ Hatchback, // 1
+ SUV = 254, // 254
+ Hybrid // 255
+};
+
+void WriteByteToFile(uint8_t InputValue)
+{
+ // Serialisierung von InputValue in eine Datei
+}
+
+void WritePreferredCarTypeToFile(ECarTypes InputCarType)
+{
+ // Wird nicht kompilieren, da "ECarTypes" ein "uint8_t" ist, da das enum
+ // als "enum class" deklariert wurde!
+ WriteByteToFile(InputCarType);
+}
+
+//////////////////////////////////////////
+// Klassen und objekorientierte Programmierung
+//////////////////////////////////////////
+
+// Erstes Beispiel einer Klasse
+#include <iostream>
+
+// Deklaration einer Klasse.
+// Klassen werden üblicherweise im header (.h oder .hpp) deklariert.
+class Dog
+{
+ // Member Variablen und Funktionen sind private per default (standard).
+ std::string name;
+ int weight;
+
+// Alle nachfolgenden member sind "public" bis
+// "private:" oder "protected:" auftritt.
+public:
+
+ // Standard Konstruktor
+ Dog();
+
+ // Member-Funktionsdeklaration (Implementierung folgt).
+ // Bemerkung: std::string statt der Verwendung von namespace std;
+ // "using namespace" sollte niemals in einem header verwendet werden.
+ void setName(const std::string& dogsName);
+
+ void setWeight(int dogsWeight);
+
+ // Funktionen, die Objekte nicht ändern, sollten mit const deklariert werden.
+ // Funktionen müssen explizit als "virtual" deklariert werden, um in einer
+ // abgeleiteten Klassen überschrieben zu werden.
+ // Aus performance Gründen sind Funktionen nicht per default virtual.
+ virtual void print() const;
+
+ // Funktionen können ebenfalls im class body definiert werden.
+ // Derart definierte Funktionen sind automatisch "inline".
+ void bark() const { std::cout << name << " barks!\n"; }
+
+ // Neben Konstruktoren, bietet C++ Destruktoren.
+ // Diese werden aufgerufen, wenn ein Objekt freigegeben wird oder
+ // seinen Wertebereich verlässt.
+ // Dies ermöglicht mächtige Paradigmen, wie auch RAII.
+ // Destruktoren sollten virtual sein, wenn eine Klasse von ihr
+ // abgeleitet wird. Ist dieser nicht virtual, dann wird der
+ // Destruktor der abgeleiteten Klasse nicht aufgerufen, insofern
+ // das Objekt durch eine Referenz/Pointer der Basisklasse entfernt wird.
+ virtual ~Dog();
+
+}; // Ein Semikolon schließt die Definition der Klasse ab.
+
+// Klassen-Member-Funktionen sind üblicherweise in der .cpp Datei implementiert.
+Dog::Dog()
+{
+ std::cout << "A dog has been constructed\n";
+}
+
+// Objekte sollten als Referenz übergeben werden und wenn diese nicht
+// verändert werden sollen, sollte das Objekt als const Referenz übergeben werden.
+void Dog::setName(const std::string& dogsName)
+{
+ name = dogsName;
+}
+
+void Dog::setWeight(int dogsWeight)
+{
+ weight = dogsWeight;
+}
+
+// "Virtual" wird nur bei der Deklaration benötigt und nicht bei der Definition.
+void Dog::print() const
+{
+ std::cout << "Dog is " << name << " and weighs " << weight << "kg\n";
+}
+
+Dog::~Dog()
+{
+ std::cout << "Goodbye " << name << "\n";
+}
+
+int main()
+{
+ Dog myDog; // Ausgabe: "A dog has been constructed"
+ myDog.setName("Barkley");
+ myDog.setWeight(10);
+ myDog.print(); // Ausgabe: "Dog is Barkley and weighs 10 kg"
+ return 0;
+} // Ausgabe: "Goodbye Barkley"
+
+// Diese Klasse erbt alles was public bzw. protected ist von der Dog-Klasse
+// und darüber hinaus auch private Methoden/Attribute, jedoch kann auf diese
+// nicht direkt zugegriffen werden. Lediglich über public/procted getter/setter.
+class OwnedDog : public Dog {
+
+public:
+ void setOwner(const std::string& dogsOwner);
+
+ // Überschreibt das Verhalten der "print" Funktion für alle "OwnedDogs".
+ // Siehe: http://en.wikipedia.org/wiki/Polymorphism_(computer_science)#Subtyping
+ // für eine grundlegende Einführung in "Subtype Polymorphismus".
+ // Das "override" Schlüsselwort ist optional, aber stellt sicher, dass die
+ // Methode der Basisklasse tatsächlich überschrieben wurde.
+ void print() const override;
+
+private:
+ std::string owner;
+};
+
+// Die zugehörige .cpp Datei
+void OwnedDog::setOwner(const std::string& dogsOwner)
+{
+ owner = dogsOwner;
+}
+
+void OwnedDog::print() const
+{
+ Dog::print(); // Ruft die "print" Funktion der Basisklasse auf.
+ std::cout << "Dog is owned by " << owner << "\n";
+ // Ausgaben: "Dog is <name> and weights <weight>"
+ // "Dog is owned by <owner>"
+}
+
+//////////////////////////////////////////
+// Initialisierung und Operatorüberladung
+//////////////////////////////////////////
+
+// In C++ können Operatoren wie: +, -, *, / etc. überladen werden.
+// Dies wird umgesetzt, indem eine entsprechende Funktion definiert wird,
+// welche immer dann aufgerufen wird, sobald der Operator verwendet wird.
+#include <iostream>
+using namespace std;
+
+class Point
+{
+public:
+ // Member Variablen können mit einem default Wert initialisiert werden.
+ double x = 0;
+ double y = 0;
+
+ // Definition des Standard Konstruktor, welcher nichts tut
+ // außer den Punkt auf den default Wert (0,0) zu setzen.
+ Point() { };
+
+ // Die nachfolgende Syntax ist bekannt als "initialization list"
+ // und ist eine gängige Art Klassen-Member zu initialisieren.
+ Point (double a, double b) :
+ x(a),
+ y(b)
+ { /* Außschließliche Initialisierung der Werte */ }
+
+ // Überladung des "+" Operator.
+ Point operator+(const Point& rhs) const;
+
+ // Überladung des "+=" Operator
+ Point& operator+=(const Point& rhs);
+
+ // Sinnhaft wäre es an dieser Stelle den "-" und "-=" Operator
+ // ebenfalls zu überladen.
+};
+
+Point Point::operator+(const Point& rhs) const
+{
+ // Erzeugung eines neuen Punkts, welcher die Summe aus sich
+ // selbst und "rhs" bildet
+ return Point(x + rhs.x, y + rhs.y);
+}
+
+Point& Point::operator+=(const Point& rhs)
+{
+ x += rhs.x;
+ y += rhs.y;
+ return *this;
+}
+
+int main ()
+{
+ Point up (0,1);
+ Point right (1,0);
+
+ // Ruft den + Operator mit den entsprechenden Parametern auf.
+ Point result = up + right;
+ // Ausgabe: "Result is upright (1,1)"
+ cout << "Result is upright (" << result.x << ',' << result.y << ")\n";
+ return 0;
+}
+
+/////////////////////
+// Templates
+/////////////////////
+
+// Templates in C++ werden in erster Linie dafür verwendet generisch zu programmieren.
+// Sie unterstützen explizite und partielle Spezialisierung und darüber hinaus können
+// sie für funktionale Klassen verwendet werden.
+// Tatsächlich bilden templates die Turing-Vollständigkeit
+// (universelle Programmierbarkeit) ab.
+
+
+// Zu Beginn ein einführendes Beispiel der generischen Programmierung.
+// Die Definition einer Klasse bzw. Funktion, welche mit dem Typ T parametriert wird.
+template<class T>
+class Box
+{
+public:
+ // T repräsentiert an dieser Stelle einen beliebigen Typen.
+ void insert(const T&) { ... }
+};
+
+// Während der Kompilierung generiert der Compiler Kopien für jedes template, wobei
+// hierbei die Parameter substituiert werden. Somit muss bei jedem Aufruf die gesamte
+// Definition der Klasse zur Verfügung stehen. Aus diesem Grund wird ein Template
+// komplett im header definiert.
+
+// Erzeugung einer Template-Klasse auf dem stack:
+Box<int> intBox;
+
+// eine der zu erwartenden Verwendungen:
+intBox.insert(123);
+
+// Verschachtelungen von Templates sind möglich.
+Box<Box<int> > boxOfBox;
+boxOfBox.insert(intBox);
+
+// Bis C++11 war es erforderlich ein Leerzeichen zwischen '>' einzufügen,
+// andernfalls wurde es als '>>' geparsed (right shift).
+
+// Manchmal ist folgende Notation anzutreffen:
+// template<typename T>
+// Das 'class' Schlüsselwort und das 'typename' Schlüsselwort
+// sind fast identisch hinsichtlich der Funktionalität. Weitere
+// Informationen auf: http://en.wikipedia.org/wiki/Typename
+
+// Eine template-Funktion:
+template<class T>
+void barkThreeTimes(const T& input)
+{
+ input.bark();
+ input.bark();
+ input.bark();
+}
+
+// Hierbei ist zu beachten, dass an dieser Stelle nichts über den Typen des Parameters
+// definiert wurde. Der Kompiler wird bei jedem Aufruf bzw. jeder Erzeugung den Typen
+// prüfen. Somit funktioniert die zuvor definierte Funktion für jeden Typ 'T', die die
+// const Methode 'bark' implementiert hat.
+
+Dog fluffy;
+fluffy.setName("Fluffy")
+barkThreeTimes(fluffy); // Gibt "Fluffy barks" dreimal aus.
+
+// Template Parameter müssen keine Klassen sein.
+template<int Y>
+void printMessage()
+{
+ cout << "Learn C++ in " << Y << " minutes!" << endl;
+}
+
+// Des Weiteren können templates aus Effizienzgründen genauer spezifiziert werden.
+// Selbstverständlich sind reale-Problemen, welche genauer spezifiziert werden nicht
+// derart trivial. Auch wenn alle Parameter explizit definiert wurden, muss die
+// Funktion oder Klasse als template deklariert werden.
+template<>
+void printMessage<10>()
+{
+ cout << "Learn C++ faster in only 10 minutes!" << endl;
+}
+
+printMessage<20>(); // Gibt "Learn C++ in 20 minutes!" aus.
+printMessage<10>(); // Gibt "Learn C++ faster in only 10 minutes!" aus.
+
+
+/////////////////////
+// Ausnahme Behandlungen (Exception-Handling)
+/////////////////////
+
+// Die Standard Bibliothek bietet einige exceptions.
+// Siehe: http://en.cppreference.com/w/cpp/error/exception.
+// Grundsätzlich können alle Typen als exception geworfen werden.
+#include <exception>
+#include <stdexcept>
+
+// Alle exceptions, die in dem "try" Block geworfen werden, können mittels
+// "catch" abgefangen werden.
+try
+{
+ // exceptions sollten nicht auf dem heap mithilfe
+ // von "new" allokiert werden.
+ throw std::runtime_error("A problem occurred");
+}
+
+// Exceptions sollten als const Referenz abgefangen werden
+// insofern diese Objekte sind.
+catch (const std::exception& ex)
+{
+ std::cout << ex.what();
+}
+
+// Abfangen aller Exceptions, welche zuvor nicht abgefangen wurden.
+catch (...)
+{
+ std::cout << "Unknown exception caught";
+ throw; // Erneutes werfen der exception
+}
+
+///////
+// RAII
+///////
+
+// RAII steht für "Resource Acquisition Is Initialization".
+// Oft wird dies als eines der wichtigsten Paradigmen in C++ betrachtet.
+// RAII beschreibt das Konzept, dass der Konstruktor für ein Objekt
+// die Ressourcen akquiriert und der Destruktor diese freigibt.
+
+// Zum Verständnis, warum dies sinnvoll ist, nachfolgend
+// ein einführendes Beispiel:
+void doSomethingWithAFile(const char* filename)
+{
+ // Wir nehmen an, dass nichts schiefgehen wird.
+ FILE* fh = fopen(filename, "r"); // Öffnen der Datei im read-mode.
+
+ doSomethingWithTheFile(fh);
+ doSomethingElseWithIt(fh);
+
+ fclose(fh); // Schließen des file-handle.
+}
+
+// Unglücklicherweise ist die Fehlerbehandlung äußerst kompliziert.
+// Sollte fopen fehlschlagen und "doSomethingWithTheFile" bzw.
+// "doSomethingElseWithIt", geben diese einen Fehlercode zurück.
+// (Exceptions sind eine bevorzugte Möglichkeit Fehler abzufangen
+// , allerdings bei einigen Programmierern, besonders solchen die einen C
+// background besitzen, ein unbeliebtes Mittel zur Fehlerbehandlung).
+// Nun müssen wir jeden Aufruf auf mögliche auftretende Fehler überprüfen.
+bool doSomethingWithAFile(const char* filename)
+{
+ FILE* fh = fopen(filename, "r"); // Öffnet die Datei im read-mode
+ if (fh == nullptr) // Der Pointer ist bei einem Fehler NULL .
+ return false; // Benachrichtigt den Aufrufer über den Fehler.
+
+ // Wir nehmen an, dass jede Funktion false zurückgibt, in einem Fehlerfall
+ if (!doSomethingWithTheFile(fh))
+ {
+ fclose(fh); // File handle schließen.
+ return false; // Fehler "melden".
+ }
+
+ if (!doSomethingElseWithIt(fh))
+ {
+ fclose(fh); // File handle schließen.
+ return false; // Fehler "melden".
+ }
+
+ fclose(fh); // File handle schließen.
+ return true; // Erfolg "melden".
+}
+
+// C-Programmierer handhaben dies häufig durch goto-Anweisungen:
+bool doSomethingWithAFile(const char* filename)
+{
+ FILE* fh = fopen(filename, "r");
+ if (fh == nullptr)
+ return false;
+
+ if (!doSomethingWithTheFile(fh))
+ goto failure;
+
+ if (!doSomethingElseWithIt(fh))
+ goto failure;
+
+ fclose(fh); // File handle schließen.
+ return true; // Erfolg "melden".
+
+failure:
+ fclose(fh);
+ return false; // Fehler "melden".
+}
+
+// Insofern Funktionen Fehler durch exceptions indizieren,
+// ist dies "sauberer", aber immer noch suboptimal.
+void doSomethingWithAFile(const char* filename)
+{
+ FILE* fh = fopen(filename, "r"); // Öffnet die Datei im read-mode
+ if (fh == nullptr)
+ throw std::runtime_error("Could not open the file.");
+
+ try
+ {
+ doSomethingWithTheFile(fh);
+ doSomethingElseWithIt(fh);
+ }
+ catch (...)
+ {
+ // Im Fehlerfall sollte sichergestellt sein, dass die
+ // Datei geschlossen wird.
+ fclose(fh);
+ throw; // Erneutes werfen der exception
+ }
+
+ fclose(fh); // Schließen der Datei
+}
+
+// Folgendes ist mit der C++ file stream Klasse (fstream) zu vergleichen.
+// fstream verwendet den Destruktor, um die Datei zu schließen.
+// Der obige Destruktor wird automatisch aufgerufen, sobald das Objekt
+// den Gültigkeitsbereich verlässt.
+void doSomethingWithAFile(const std::string& filename)
+{
+ // ifstream entspricht der Kurzform von "input file stream".
+ std::ifstream fh(filename); // Öffnen der Datei
+
+ doSomethingWithTheFile(fh);
+ doSomethingElseWithIt(fh);
+
+} // Die Datei wird automatisch vom Destruktor geschlossen.
+
+// Diese Vorgehensweise bietet massive Vorteile:
+// 1. Egal was passiert, die Ressource (das Datei-Handle) wird aufgelöst,
+// insofern der Destruktor korrekt beschrieben wurde. Es ist möglich
+// zu vergessen das Datei-Handle zu schließen, was zu einem "leak" der
+// entsprechenden Ressource führt.
+// 2. Der Code selbst ist wesentlich "sauberer".
+// Der Destruktor wird das Datei-Handle im Hintergrund schließen und der
+// Programmierer muss sich darum keinerlei Sorgen machen.
+// 3. Der Code ist "exception sicher".
+// Egal wo die exception geworfen wird, das Aufräumen wird definitiv vollzogen.
+
+// Der gesamte idiomatische C++ Code verwendet RAII für alle Ressourcen.
+// Weitere Beispiele:
+// - Speicher verwenden "unique_ptr" und "shared_ptr".
+// - Container - verkettete Listen (linked list), vector (selbst organisierende
+// Arrays), hash maps, etc., entfernen deren Inhalt, wenn diese außerhalb des
+// Gültigkeitsbereichs laufen.
+// - Mutex´s verwenden lock_guard und unique_lock.
+
+/////////////////////
+// Container
+/////////////////////
+
+// Die Container der Standard template Bibliothek beinhaltet einige vordefinierter templates.
+// Diese verwalten die Speicherbereiche für die eigenen Elemente und stellen Member-Funktionen
+// für den Zugriff und die Maniplulation bereit.
+
+// Beispielhafte Container:
+
+// Vector (dynamisches array)
+// Erlaubt das Definieren von Arrays oder Listen zur Laufzeit
+#include <vector>
+string val;
+vector<string> my_vector; // Initialisierung des Vectors.
+cin >> val;
+my_vector.push_back(val); // Fügt den Wert "val" zum Vektor "my_vector" hinzu.
+my_vector.push_back(val); // Fügt den Wert "val" zum Vektor "my_vector" hinzu (nun zwei Elemente).
+
+// Für die Iteration über Vektoren stehen zwei Methodiken zu Verfügung:
+// Entweder die klassische Iteration über den Index:
+for (int i = 0; i < my_vector.size(); i++)
+{
+ cout << my_vector[i] << endl; // Zugriff auf die Elemente des Vektors über den [] Operator
+}
+
+// Oder die Verwendung von Iteratoren:
+vector<string>::iterator it; // Initialisierng des Iterators.
+for (it = my_vector.begin(); it != my_vector.end(); ++it)
+{
+ cout << *it << endl;
+}
+
+// Set (Mengen)
+// Sets sind Container, welche einzigartige Elemente beinhalten die einer
+// spezifischen Ordnung folgen.
+
+#include<set>
+set<int> ST; // Initialisierung des Sets mit einem Integer Datentyp.
+ST.insert(30); // Einfügen des Werts 30 in das Set ST
+ST.insert(10); // Einfügen des Werts 10 in das Set ST
+ST.insert(20); // Einfügen des Werts 20 in das Set ST
+ST.insert(30); // Einfügen des Werts 30 in das Set ST
+// Folgende Elemente befinden sich nun in dem Set:
+// 10 20 30
+
+// Entfernen eines Elements:
+ST.erase(20);
+
+// Set ST: 10 30
+// Für das iterieren verwenden wir Iteratoren:
+set<int>::iterator it;
+
+for(it=ST.begin();it<ST.end();it++)
+{
+ cout << *it << endl;
+}
+
+// Ausgabe:
+// 10
+// 30
+
+// Zum leeren des gesamten Container wird die Methode
+// Container._name.clear() verwendet.
+ST.clear();
+cout << ST.size(); // Ausgabe der Set-Größe
+
+// Ausgabe: 0
+
+// Bemerkung: für mehrdeutige Elemente werden multisets verwendet.
+// Für hash-Sets sollten unordered_set´s verwendet werden, da diese
+// wesentlich effizienter sind, allerdings keiner Ordnung folgen.
+// Verfügbar sind diese Features ab C++11.
+
+// Map
+// Maps speichern Elemente, welche einer Kombination aus "Key"
+// und "Value" folgen.
+
+#include<map>
+map<char, int> mymap; // Initialisierung der Map: char -> Key, int -> Value.
+
+mymap.insert(pair<char,int>('A',1)); // Einfügen des Werts "1" für den Key "A".
+
+mymap.insert(pair<char,int>('Z',26)); // Einfügen des Werts "26" für den Key "Z".
+
+// Das Iterieren über Maps:
+map<char,int>::iterator it;
+for (it=mymap.begin(); it!=mymap.end(); ++it)
+ std::cout << it->first << "->" << it->second << '\n';
+
+// Ausgabe:
+// A->1
+// Z->26
+
+// Für das Finden des dazugehörigen Value des Keys.
+it = mymap.find('Z');
+cout << it->second;
+
+// Ausabe: 26
+
+// Bemerkung: für "hash maps" sollten die "unordered_map´s" verwendet werden. Diese
+// sind effizienter und benötigen keine Reihenfolge. "unordered_maps" sind ab
+// C++11 verfügbar.
+
+// Container für nicht-primitive Datentypen benötigen Vergleichsfunktionen im Objekt selbst,
+// oder als Funktionspointer. Primitive Datentypen besitzen default-Vergleichsfunktionen.
+// Allerdings können diese überschrieben werden.
+class Foo
+{
+public:
+ int j;
+ Foo(int a) : j(a) {}
+};
+
+struct compareFunction
+{
+ bool operator()(const Foo& a, const Foo& b) const
+ {
+ return a.j < b.j;
+ }
+};
+
+// Folgender Code ist nicht valide, könnte aber von einigen Compilern
+// als valide angesehen werden:
+// std::map<Foo, int> fooMap;
+std::map<Foo, int, compareFunction> fooMap;
+fooMap[Foo(1)] = 1;
+fooMap.find(Foo(1)); // Wahr
+
+
+///////////////////////////////////////
+// Lambda Ausdrücke (C++11 und höher)
+///////////////////////////////////////
+
+// Lambdas sind eine gängige Methodik um anonyme Funktionen an dem
+// Ort der Verwendung zu definieren. Darüber hinaus auch bei der
+// Verwendung von Funktionen als Argument einer Funktion.
+
+// Nehmen wir an es soll ein Vektor von "pairs" (Paaren) mithilfe
+// des zweiten Werts des "pairs" sortiert werden.
+
+vector<pair<int, int> > tester;
+tester.push_back(make_pair(3, 6));
+tester.push_back(make_pair(1, 9));
+tester.push_back(make_pair(5, 0));
+
+// Übergabe des Lambda-Ausdrucks als drittes Argument für die nachfolgende Sortierfunktion.
+sort(tester.begin(), tester.end(), [](const pair<int, int>& lhs, const pair<int, int>& rhs)
+{
+ return lhs.second < rhs.second;
+});
+
+// Beachte den Syntax von Lambda-Ausdrücken.
+// Die [] im Lambda Ausdruck werden für die Variablen verwendet.
+// Diese so genannte "capture list" definiert, was außerhalb des Lambdas,
+// innerhalb der Funktion verfügbar sein soll und in welcher Form.
+// Dies kann folgendes sein:
+// 1. ein Wert [x]
+// 2. eine Referenz [&x]
+// 3. eine beliebige Variable, welche sich im Gültigkeitsbereich durch
+// die Referenz [&] befindet.
+// 4. wie bei 3. aber mithilfe des Werts [=]
+// Beispiel:
+
+vector<int> dog_ids;
+
+for(int i = 0; i < 3; i++)
+{
+ dog_ids.push_back(i);
+}
+
+int weight[3] = {30, 50, 10};
+
+// Nehmen wir an wir möchten die "dog_ids" gemäß des Gewichts des Hundes sortieren.
+// So sollten sich die "dog_ids" wie folgt verhalten: [2, 0, 1]
+
+// Hier werden Lambdas praktisch:
+sort(dog_ids.begin(), dog_ids.end(), [&weight](const int &lhs, const int &rhs)
+{
+ return weight[lhs] < weight[rhs];
+});
+
+
+// Weiterführender Link über Lambda-Ausdrücke:
+// http://stackoverflow.com/questions/7627098/what-is-a-lambda-expression-in-c11
+
+///////////////////////////////
+// Range For (C++11 und höher)
+///////////////////////////////
+
+// Range-For Schleifen können verwendet werden, um über Container zu iterieren.
+int arr[] = {1, 10, 3};
+
+for(int elem: arr)
+{
+ cout << elem << endl;
+}
+
+// Insofern "auto" verwendet wird, muss der Typ nicht weiter beachtet werden.
+for(auto elem: arr)
+{
+ // Anweisungen ...
+}
+
+/////////////////////
+// Weiteres:
+/////////////////////
+
+// Einige Aspekte von C++ sind für Neueinsteiger häufig überraschend (aber auch für
+// C++ Veteranen).
+// Der nachfolgende Abschnitt ist leider nicht vollständig:
+// C++ ist eine der Sprachen, bei der es ein leichtes ist sich selbst ins Bein zu schießen.
+
+// Private-Methoden können überschrieben werden
+class Foo
+{
+ virtual void bar();
+};
+
+class FooSub : public Foo
+{
+ virtual void bar(); // Überschreibt Foo::bar!
+};
+
+// 0 == false == NULL
+bool* pt = new bool;
+*pt = 0; // Setzt den Wert des Pointers 'pt' auf false.
+pt = 0; // Setzt 'pt' auf den "null-pointer". Keine Compiler-Warnung.
+
+// nullptr sollte dieses Problem nicht lösen:
+int* pt2 = new int;
+*pt2 = nullptr; // Kompiliert nicht.
+pt2 = nullptr; // Setzt pt2 auf null.
+
+// Eine Ausnahme bilden bool´s.
+// Dies erlaubt es "null-pointer" zu testen: if(!ptr)
+// Die Konsequenz ist jedoch, dass dem nullptr ein bool zugewiesen werden kann.
+*pt = nullptr; // Kompiliert auch, wenn '*pt' ein bool ist!
+
+// '=' != '=' != '='!
+// Ruft Foo::Foo(const Foo&) auf, oder den Kopierkonstruktor
+Foo f2;
+Foo f1 = f2;
+
+// Ruft Foo::Foo(const Foo&) auf, aber kopiert lediglich den "Foo" Teil von
+// "fooSub". Alle zusätzlichen Member werden verworfen. Diese eigenartige Verhalten
+// wird auch "object slicing" genannt.
+FooSub fooSub;
+Foo f1 = fooSub;
+
+// Ruft Foo::operator=(Foo&) oder eine andere Variante auf.
+Foo f1;
+f1 = f2;
+
+///////////////////////////////////////
+// Tuple (C++11 und höher)
+///////////////////////////////////////
+
+#include<tuple>
+
+// Konzeptionell sind Tuple´s alten Datenstrukturen sehr ähnlich, allerdings haben diese keine
+// bezeichneten Daten-Member, sondern werden durch die Reihenfolge angesprochen.
+
+// Erstellen des Tuples und das Einfügen eines Werts.
+auto first = make_tuple(10, 'A');
+const int maxN = 1e9;
+const int maxL = 15;
+auto second = make_tuple(maxN, maxL);
+
+// Ausgabe der Elemente des "first" Tuple.
+cout << get<0>(first) << " " << get<1>(first) << "\n"; // Ausgabe : 10 A
+
+// Ausgabe der Elemente des "second" Tuple.
+cout << get<0>(second) << " " << get<1>(second) << "\n"; // Ausgabe: 1000000000 15
+
+int first_int;
+char first_char;
+tie(first_int, first_char) = first;
+cout << first_int << " " << first_char << "\n"; // Ausgabe : 10 A
+
+// Tuple können auch wie folgt erzeugt werden:
+
+tuple<int, char, double> third(11, 'A', 3.14141);
+// tuple_size gibt die Anzahl der Elemente in einem Tuple zurück.
+// Als "constexpr".
+
+cout << tuple_size<decltype(third)>::value << "\n"; // prints: 3
+
+// tuple_cat fügt die Elemente eines Tuples aneinander (in der selben Reihenfolge).
+
+auto concatenated_tuple = tuple_cat(first, second, third);
+// concatenated_tuple wird zu = (10, 'A', 1e9, 15, 11, 'A', 3.14141)
+
+cout << get<0>(concatenated_tuple) << "\n"; // Ausgabe: 10
+cout << get<3>(concatenated_tuple) << "\n"; // Ausgabe: 15
+cout << get<5>(concatenated_tuple) << "\n"; // Ausgabe: 'A'
+
+
+///////////////////////////////////
+// Logische- und Bitoperatoren
+//////////////////////////////////
+
+// Die meisten Operatoren in C++ entsprechen denen aus anderen Sprachen
+
+// Logische Operatoren.
+// C++ verwendet so genannte "Short-circuit" Evaluierung für Boolean-Ausdrücke.
+// Das zweite Argument wird ausgeführt bzw. evaluiert, wenn das erste Argument genügt,
+// um den Ausdruck zu bestimmen.
+
+true && false // Führt **logisches und** aus.
+true || false // Führt **logisches oder** aus.
+! true // Führt **logisches nicht** aus.
+
+// Anstelle von Symbolen können auch Schlüsselwörter verwendet werden.
+true and false // Führt **logisches und** aus.
+true or false // Führt **logisches oder** aus.
+not true // Führt **logisches nicht** aus.
+
+// Bitoperationen
+
+// **<<** Links-Shift
+// **>>** Rechts-Shift
+
+~4 // Führt bitweises nicht aus.
+4 | 3 // Führt bitweises oder aus.
+4 & 3 // Führt bitweises und aus.
+4 ^ 3 // Führt bitweises xor aus.
+
+// Gleichwertige Schlüsselwörter:
+compl 4 // Führt bitweises nicht aus.
+4 bitor 3 // Führt bitweises oder aus.
+4 bitand 3 // Führt bitweises und aus.
+4 xor 3 // Führt bitweises xor aus.
+
+
+```
+Weiterführende Literatur:
+
+* Aktuelle Sprachen-Referenz [CPP Reference](http://cppreference.com/w/cpp).
+* Zusätzliches: [CPlusPlus](http://cplusplus.com).
+* Grundlagen Tutorial: [TheChernoProject - C++](https://www.youtube.com/playlist?list=PLlrATfBNZ98dudnM48yfGUldqGD0S4FFb).
diff --git a/de-de/python-de.html.markdown b/de-de/python-de.html.markdown
index d3e0fc26..ee77683e 100644
--- a/de-de/python-de.html.markdown
+++ b/de-de/python-de.html.markdown
@@ -386,25 +386,73 @@ 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. Module
+####################################################
+
+# Wir können Module importieren
+import math
+print math.sqrt(16) #=> 4.0
+
+# Wir können auch nur spezielle Funktionen eines Moduls importieren
+from math import ceil, floor
+print ceil(3.7) #=> 4.0
+print floor(3.7) #=> 3.0
+
+# Wir können auch alle Funktionen eines Moduls importieren
+# Warnung: Dies wird nicht empfohlen
+from math import *
+
+# Wir können Modulnamen abkürzen
+import math as m
+math.sqrt(16) == m.sqrt(16) #=> True
+
+# Module sind in Python nur gewöhnliche Dateien. Wir
+# können unsere eigenen schreiben und importieren. Der Name des
+# Moduls ist der Dateiname.
+
+# 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.
+
+
####################################################
-## 5. Klassen
+## 6. Klassen
####################################################
-# Wir bilden die Unterklasse eines Objekts, um Klassen zu erhalten.
+# 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
+ # 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.
+ # 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
@@ -416,56 +464,287 @@ class Human(object):
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 Instanz einer Klasse erstellen
-i = Human(name="Ian")
-print i.say("hi") # gibt "Ian: hi" aus
+# Eine weitere Klassendefinition
+# bat.py
-j = Human("Joel")
-print j.say("hello") #gibt "Joel: hello" aus
+class Bat:
-# Rufen wir mal unsere Klassenmethode auf
-i.get_species() #=> "H. sapiens"
+ species = 'Baty'
-# Ändern wir mal das gemeinsame Attribut
-Human.species = "H. neanderthalensis"
-i.get_species() #=> "H. neanderthalensis"
-j.get_species() #=> "H. neanderthalensis"
+ def __init__(self, can_fly=True):
+ self.fly = can_fly
-# Aufruf der statischen Methode
-Human.grunt() #=> "*grunt*"
+ # 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
+
+
####################################################
-## 6. Module
-####################################################
-
-# Wir können Module importieren
-import math
-print math.sqrt(16) #=> 4.0
+## 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]
-# Wir können auch nur spezielle Funktionen eines Moduls importieren
-from math import ceil, floor
-print ceil(3.7) #=> 4.0
-print floor(3.7) #=> 3.0
+# Decorators
+# In diesem Beispiel umschliesst "beg" "say". Wenn say_please True ist, wird die zurückgegebene Nachricht geändert.
+from functools import wraps
-# Wir können auch alle Funktionen eines Moduls importieren
-# Warnung: Dies wird nicht empfohlen
-from math import *
+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
-# Wir können Modulnamen abkürzen
-import math as m
-math.sqrt(16) == m.sqrt(16) #=> True
+ return wrapper
-# Module sind in Python nur gewöhnliche Dateien. Wir
-# können unsere eigenen schreiben und importieren. Der Name des
-# Moduls ist der Dateiname.
+@beg
+def say(say_please=False):
+ msg = "Can you buy me a beer?"
+ return msg, say_please
-# Wir können auch die Funktionen und Attribute eines
-# Moduls herausfinden.
-import math
-dir(math)
+print(say()) # Can you buy me a beer?
+print(say(say_please=True)) # Can you buy me a beer? Please! I am poor :(
```