diff options
Diffstat (limited to 'de-de')
-rw-r--r-- | de-de/asciidoc-de.html.markdown | 6 | ||||
-rw-r--r-- | de-de/bash-de.html.markdown | 4 | ||||
-rw-r--r-- | de-de/c++-de.html.markdown | 1158 | ||||
-rw-r--r-- | de-de/dhall-de.html.markdown | 380 | ||||
-rw-r--r-- | de-de/dynamic-programming-de.html.markdown | 6 | ||||
-rw-r--r-- | de-de/git-de.html.markdown | 14 | ||||
-rw-r--r-- | de-de/hq9+-de.html.markdown | 43 | ||||
-rw-r--r-- | de-de/make-de.html.markdown | 3 | ||||
-rw-r--r-- | de-de/markdown-de.html.markdown | 2 | ||||
-rw-r--r-- | de-de/nix-de.html.markdown | 22 | ||||
-rw-r--r-- | de-de/opencv-de.html.markdown | 153 | ||||
-rw-r--r-- | de-de/paren-de.html.markdown | 200 | ||||
-rw-r--r-- | de-de/python-de.html.markdown | 359 | ||||
-rw-r--r-- | de-de/python3-de.html.markdown | 18 | ||||
-rw-r--r-- | de-de/rst-de.html.markdown | 119 | ||||
-rw-r--r-- | de-de/shutit-de.html.markdown | 330 | ||||
-rw-r--r-- | de-de/yaml-de.html.markdown | 4 |
17 files changed, 2742 insertions, 79 deletions
diff --git a/de-de/asciidoc-de.html.markdown b/de-de/asciidoc-de.html.markdown index 60f8fa61..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 und 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/bash-de.html.markdown b/de-de/bash-de.html.markdown index 7928b136..3fb3e71f 100644 --- a/de-de/bash-de.html.markdown +++ b/de-de/bash-de.html.markdown @@ -180,7 +180,7 @@ esac # 'for' Schleifen iterieren über die angegebene Zahl von Argumenten: # Der Inhalt von $Variable wird dreimal ausgedruckt. -for $Variable in {1..3} +for Variable in {1..3} do echo "$Variable" done @@ -217,7 +217,7 @@ done function foo () { echo "Argumente funktionieren wie bei skripts: $@" - echo Und: $1 $2..." + echo "Und: $1 $2..." echo "Dies ist eine Funktion" return 0 } diff --git a/de-de/c++-de.html.markdown b/de-de/c++-de.html.markdown new file mode 100644 index 00000000..87e75ad6 --- /dev/null +++ b/de-de/c++-de.html.markdown @@ -0,0 +1,1158 @@ +--- +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"] + - ["caminsha", "https://github.com/caminsha"] +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 seine Syntax kann sie durchaus schwieriger und komplexer als neuere Sprachen sein. + +Sie ist weit verbreitet, weil sie in Maschinen-Code kompiliert, welcher 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 die +// 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 (Namensrä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 alle 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 zuzuweisen. 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 Compiler 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 Probleme, 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 vordefinierte Templates. +// Diese verwalten die Speicherbereiche für die eigenen Elemente und stellen Member-Funktionen +// für den Zugriff und die Manipulation 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 Containers 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 die 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 Tupel alten Datenstrukturen sehr ähnlich, allerdings haben diese keine +// bezeichneten Daten-Member, sondern werden durch die Reihenfolge angesprochen. + +// Erstellen des Tupels 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 Tupels 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/dhall-de.html.markdown b/de-de/dhall-de.html.markdown new file mode 100644 index 00000000..385c88be --- /dev/null +++ b/de-de/dhall-de.html.markdown @@ -0,0 +1,380 @@ +--- +language: Dhall +contributors: + - ["Gabriel Gonzalez", "http://www.haskellforall.com/"] +translators: + - ["Profpatsch", "http://profpatsch.de"] +filename: learndhall-de.py +lang: de-de +--- + +Dhall ist eine programmierbare Konfigurationssprache und bietet eine +nicht-repetetive Alternative zu YAML. + +Man kann Dhall sehen als: JSON + Funktionen + Typen + Importsystem + +Obwohl Dhall programmierbar ist, ist die Sprache nicht +turingvollständig. Viele von Dhalls Features benutzen diese +Einschränkung, um stärkere Sicherheitsgarantien zu bieten und besseres +Tooling zu ermöglichen. + +```haskell +-- einzeiliger Kommentar + +{- mehrzeiliger Kommentar + + Unicode funktioniert 🙂 + + Diese Datei ist eine valide Dhall-Expression und evaluiert zu einem + großen Record, welcher die Ergebnisse jedes Schritts beinhaltet. + + Das Ergebnis kann angezeigt werden, indem man die Datei evaluiert: + + $ dhall --file learndhall.dhall + + {- Kommentare können verschachtelt sein -} +-} + +let greeting = "Hallo, Welt!" + +let fruits = "🍋🍓🍍🍉🍌" + +let interpolation = "Ein paar leckere Früchte: ${fruits}" + +let multilineText {- Inline-Kommentare funktionieren ebenfalls -} = + '' + In Multiline-Text-Literals wird Whitespace am Anfang der Zeile + entfernt. + + Das bedeutet Text kann frei eingerückt oder ausgerückt werden, + ohne dass sich der Inhalt des Strings ändert. + + Relative Einrückungen bleiben erhalten. + + Ansonsten wird das Text-Literal verbatim erhalten, ähnlich + zu “literal”-Multiline-Strings in YAML. + '' + +let bool = True + +-- Typannotationen für Bindings sind optional, aber hilfreich, also +-- benutzen wir sie hier. +let annotation : Bool = True + +let renderedBool : Text = if bool then "True" else "False" + +-- Natürliche Zahlen sind nicht-negativ und vorzeichenlos. +let naturalNumber : Natural = 42 + +-- Integer können negativ sein, brauchen aber ein explizites Vorzeichen. +let positiveInteger : Integer = +1 + +let negativeInteger : Integer = -12 + +let pi : Double = 3.14159265359 + +{- Identifier dürfen eine große Anzahl an verschiedenen Zeichen + beinhalten (wie z.B. Anführungszeichen oder Whitespace), wenn man + sie mit Backticks umschließt. +-} +let `Avogadro's Number` : Double = 6.0221409e+23 + +let origin : { x : Double, y : Double } = { x = 0.0, y = 0.0 } + +let somePrimes : List Natural = [ 2, 3, 5, 7, 11 ] + +{- Ein Schema ist das gleiche wie ein Typ. + + Typnamen beginnen konventionell mit einem Großbuchstaben, was + jedoch nicht erzwungen wird. +-} +let Profile : Type + = { person : + { name : Text + , age : Natural + } + , address : + { country : Text + , state : Text + , city : Text + } + } + +let bernd : Profile = + { person = + { name = "Bernd Lauert" + , age = 67 + } + , address = + { country = "Deutschland" + , state = "Bayern" + , city = "Augsburg" + } + } + +let augsburg : Text = bernd.address.city + +{- Enum-Alternativen beginnen konventionell auch mit einem + Großbuchstaben. Das wird ebenfalls nicht erzwungen. +-} +let DNA : Type = < Adenine | Cytosine | Guanine | Thymine > + +let dnaSequence : List DNA = [ DNA.Thymine, DNA.Guanine, DNA.Guanine ] + +let compactDNASequence : List DNA = + let a = DNA.Adenine + let c = DNA.Cytosine + let g = DNA.Guanine + let t = DNA.Thymine + in [ c, t, t, a, t, c, g, g, c ] + +-- Enums werden transformiert, indem man einen Record mit einem Feld +-- pro Alternative angibt. +let theLetterG : Text = + merge + { Adenine = "A" + , Cytosine = "C" + , Guanine = "G" + , Thymine = "T" + } + DNA.Guanine + +let presentOptionalValue : Optional Natural = Some 1 + +let absentOptionalValue : Optional Natural = None Natural + +let points : List { x : Double, y : Double } = + [ { x = 1.1, y = -4.2 } + , { x = 4.4, y = -3.0 } + , { x = 8.2, y = -5.5 } + ] + +{- `Natural -> List Natural` ist der Funktionstyp mit Eingabetyp + `Natural` und Ausgabetyp `List Natural`. + + Alle Funktionen in Dhall sind Anonyme Funktionen (aka. „Lambdas“), + denen man optional einen Namen geben kann. + + Die folgende Funktion beispielsweise ist äquivalent zu diesem + Python Code: + + lambda n : [ n, n + 1 ] + + ... und diesem Javascript Code: + + function (n) { return [ n, n + 1 ]; } +-} +let exampleFunction : Natural -> List Natural = + \(n : Natural) -> [ n, n + 1 ] + +-- Dhall unterstützt auch Unicode-Syntax, aber dieses Tutorial nutzt +-- die ASCII-Syntax. +let unicodeFunction : Natural → List Natural = + λ(n : Natural) → [ n, n + 1 ] + +-- Funktionsargumente brauchen keine Klammern. +let exampleFunctionApplication : List Natural = + exampleFunction 2 + +let functionOfMultipleArguments : Natural -> Natural -> List Natural = + \(x : Natural) -> \(y : Natural) -> [ x, y ] + +let functionAppliedToMultipleArguments : List Natural = + functionOfMultipleArguments 2 3 + +{- Wie `exampleFunction`, aber wir geben dem Eingabetypen + einen Namen, `n`. +-} +let namedArgumentType : forall (n : Natural) -> List Natural = + \(n : Natural) -> [ n, n + 1 ] + +{- Bekommt der Eingabetyp einen Namen, kann man ihn weiter hinten in + der gleichen Typdefinition wiederverwenden. + + Das ermöglicht Funktionen, die mit mehr als einem Eingabetypen + arbeiten können (aka. „polymorphe“ Funktionen). +-} +let duplicate : forall (a : Type) -> a -> List a = + \(a : Type) -> \(x : a) -> [ x, x ] + +let duplicatedNumber : List Natural = + duplicate Natural 2 + +let duplicatedBool : List Bool = + duplicate Bool False + +{- Die Sprache hat auch eine handvoll eingebauter polymorpher + Funktionen, wie zum Beispiel: + + List/head : forall (a : Type) -> List a -> Optional a +-} +let firstPrime : Optional Natural = List/head Natural somePrimes + +let functionOfARecord : { x : Natural, y : Natural } -> List Natural = + \(args : { x : Natural, y : Natural }) -> [ args.x, args.y ] + +let functionAppliedToARecord : List Natural = + functionOfARecord { x = 2, y = 5 } + +{- Alle Typkonversionen sind explizit. + + `Natural/show` ist eine eingebaute Funktion mit dem Typ: + + Natural/show : Natural -> Text + + ... welche `Natural`s in ihre `Text`-Repräsentation konvertiert. +-} +let typeConversion : Natural -> Text = + \(age : Natural) -> "Ich bin ${Natural/show age} Jahre alt!" + +-- Ein „Template“ ist einfach eine Funktion mit Ausgabetyp `Text`. +let mitLicense : { year : Natural, copyrightHolder : Text } -> Text = + \(args : { year : Natural, copyrightHolder : Text }) -> +'' +Copyright ${Natural/show args.year} ${args.copyrightHolder} + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +'' + +-- Template-Instanziierung ist das gleiche wie Funktionsanwendung. +let templatedLicense : Text = + mitLicense { year = 2019, copyrightHolder = "Jane Smith" } + +{- Expressions können via URL importiert werden. + + Ähnlich wie in Bash kann man Code aus dem lokalen Dateisystem + importieren (wird nicht gezeigt). + + Sicherheitsbewusste Nutzer können via URLs importierte Expressions + mit einem semantischen Integritätscheck versehen („pinnen“). + Für gepinnte Imports wird der Dhall-Interpreter jeden Versuch + vereiteln, auf der Remote-Seite die Expression zu manipulieren. + Jedoch werden Änderungen, die den Inhalt der importierten + Expression nicht verändern trotzdem akzeptiert. + + Auf diese Weise gepinnte Expressions werden auch in einem + Content-Adressable Store lokal gecached (standardmäßig in + `~/.cache/dhall`). +-} +let Natural/sum : List Natural -> Natural = + https://prelude.dhall-lang.org/Natural/sum + sha256:33f7f4c3aff62e5ecf4848f964363133452d420dcde045784518fb59fa970037 + +let twentyEight : Natural = Natural/sum somePrimes + +-- Ein „Paket“ ist einfach ein (möglicherweise verschachtelter) +-- Record, den man importiert. +let Prelude = https://prelude.dhall-lang.org/package.dhall + +let false : Bool = Prelude.Bool.not True + +-- Durch das Anhängen von `as Text` wird eine Datei verbatim +-- importiert und nicht als Dhall-Code interpretiert. +let sourceCode : Text = https://prelude.dhall-lang.org/Bool/not as Text + +-- Environment-Variablen können auch imortiert werden. +let presentWorkingDirectory = env:PWD as Text + +-- Mit `?` kann man eine “Fallback-Expression” angeben, für den Fall +-- dass ein Import fehlschlägt. +let home : Optional Text = Some env:HOME ? None Text + +-- Fallback-Expressions können auch alternative Imports enthalten. +let possiblyCustomPrelude = + env:DHALL_PRELUDE + ? https://prelude.dhall-lang.org/package.dhall + +{- Ein ausführliches Beispiel, welches mithilfe der + `generate`-Funktion eine Konfiguration für 10 Build-User generiert: + + Prelude.List.generate + : Natural -> forall (a : Type) -> (Natural -> a) -> List a +-} +let buildUsers = + let makeUser = \(user : Text) -> + let home = "/home/${user}" + let privateKey = "${home}/.ssh/id_ed25519" + let publicKey = "${privateKey}.pub" + in { home = home + , privateKey = privateKey + , publicKey = publicKey + } + + let buildUser = + \(index : Natural) -> makeUser "build${Natural/show index}" + + let Config = + { home : Text + , privateKey : Text + , publicKey : Text + } + + in Prelude.List.generate 10 Config buildUser + +-- Alle Ergebnisse in einem großen Record +in { greeting = greeting + , fruits = fruits + , interpolation = interpolation + , multilineText = multilineText + , bool = bool + , annotation = annotation + , renderedBool = renderedBool + , naturalNumber = naturalNumber + , positiveInteger = positiveInteger + , negativeInteger = negativeInteger + , pi = pi + , `Avogadro's Number` = `Avogadro's Number` + , origin = origin + , somePrimes = somePrimes + , bernd = bernd + , augsburg = augsburg + , dnaSequence = dnaSequence + , compactDNASequence = compactDNASequence + , theLetterG = theLetterG + , presentOptionalValue = presentOptionalValue + , absentOptionalValue = absentOptionalValue + , points = points + , exampleFunction = exampleFunction + , unicodeFunction = unicodeFunction + , exampleFunctionApplication = exampleFunctionApplication + , functionOfMultipleArguments = functionOfMultipleArguments + , functionAppliedToMultipleArguments = functionAppliedToMultipleArguments + , namedArgumentType = namedArgumentType + , duplicate = duplicate + , duplicatedNumber = duplicatedNumber + , duplicatedBool = duplicatedBool + , firstPrime = firstPrime + , functionOfARecord = functionOfARecord + , functionAppliedToARecord = functionAppliedToARecord + , typeConversion = typeConversion + , mitLicense = mitLicense + , templatedLicense = templatedLicense + , twentyEight = twentyEight + , false = false + , sourceCode = sourceCode + , presentWorkingDirectory = presentWorkingDirectory + , home = home + , buildUsers = buildUsers + } +``` + +Mehr Infos und Lernmaterialien gibt es auf der offiziellen Website +(Englisch), auf der man Dhall auf im Browser ausprobieren kann: + +* [https://dhall-lang.org](http://dhall-lang.org/) diff --git a/de-de/dynamic-programming-de.html.markdown b/de-de/dynamic-programming-de.html.markdown index 801d2514..58568b3b 100644 --- a/de-de/dynamic-programming-de.html.markdown +++ b/de-de/dynamic-programming-de.html.markdown @@ -68,9 +68,9 @@ for i=0 to n-1 ### Einige bekannte DP Probleme -- Floyd Warshall Algorithm - [Tutorial and C Program source code](http://www.thelearningpoint.net/computer-science/algorithms-all-to-all-shortest-paths-in-graphs---floyd-warshall-algorithm-with-c-program-source-code) -- Integer Knapsack Problem - [Tutorial and C Program source code](http://www.thelearningpoint.net/computer-science/algorithms-dynamic-programming---the-integer-knapsack-problem) -- Longest Common Subsequence - [Tutorial and C Program source code](http://www.thelearningpoint.net/computer-science/algorithms-dynamic-programming---longest-common-subsequence) +- [Floyd Warshall Algorithm - Tutorial and C Program source code](http://www.thelearningpoint.net/computer-science/algorithms-all-to-all-shortest-paths-in-graphs---floyd-warshall-algorithm-with-c-program-source-code) +- [Integer Knapsack Problem - Tutorial and C Program source code](http://www.thelearningpoint.net/computer-science/algorithms-dynamic-programming---the-integer-knapsack-problem) +- [Longest Common Subsequence - Tutorial and C Program source code](http://www.thelearningpoint.net/computer-science/algorithms-dynamic-programming---longest-common-subsequence) ## Online Ressourcen diff --git a/de-de/git-de.html.markdown b/de-de/git-de.html.markdown index a0ed120f..0896f513 100644 --- a/de-de/git-de.html.markdown +++ b/de-de/git-de.html.markdown @@ -10,7 +10,7 @@ lang: de-de Git ist eine verteilte Versions- und Quellcodeverwaltung. -Es nimmt Schnappschüsse der Projekte, um mit diesen Schnappschüssen verschiedene Versionen unterscheiden und den Quellcode verwalten zu können. +Es nimmt Schnappschüsse der Projekte auf, um mit diesen Schnappschüssen verschiedene Versionen unterscheiden und den Quellcode verwalten zu können. Anmerkung des Übersetzers: Einige englische Begriffe wie *Repository*, *Commit* oder *Head* sind idiomatische Bestandteile im Umgang mit Git. Sie wurden nicht übersetzt. @@ -20,7 +20,7 @@ Anmerkung des Übersetzers: Einige englische Begriffe wie *Repository*, *Commit* Eine Versionsverwaltung erfasst die Änderungen einer Datei oder eines Verzeichnisses im Verlauf der Zeit. -### Zentrale im Vergleich mit verteilter Versionverwaltung +### Vergleich zwischen Zentraler und verteilter Versionverwaltung * Zentrale Versionsverwaltung konzentriert sich auf das Synchronisieren, Verfolgen und Sichern von Dateien. * Verteilte Versionsverwaltung konzentriert sich auf das Teilen der Änderungen. Jede Änderung hat eine eindeutige ID. @@ -43,13 +43,13 @@ Eine Versionsverwaltung erfasst die Änderungen einer Datei oder eines Verzeichn ### Repository (Repo) -Ein Satz von Dateien, Verzeichnisen, Historieneinträgen, Commits und Heads. Stell es dir wie eine Quellcode-Datenstruktur vor, unter anderem mit der Eigenschaft, dass alle *Elemente* dir Zugriff auf die Revisionshistorie geben. +Ein Satz von Dateien, Verzeichnissen, Historieneinträgen, Commits und Heads. Stell es dir wie eine Quellcode-Datenstruktur vor, unter anderem mit der Eigenschaft, dass alle *Elemente* dir Zugriff auf die Revisionshistorie geben. Ein Repository besteht in Git aus dem .git-Verzeichnis und dem Arbeitsverzeichnis. ### .git-Verzeichnis (Teil des Repositorys) -Das .git-Verzeichnis enthält alle Einstellung, Logs, Branches, den HEAD und mehr. +Das .git-Verzeichnis enthält alle Einstellungen, Logs, Branches, den HEAD und mehr. [Ausführliche Übersicht](http://gitready.com/advanced/2009/03/23/whats-inside-your-git-directory.html) ### Arbeitsverzeichnis (Teil des Repositorys) @@ -66,7 +66,7 @@ Ein Commit ist ein Schnappschuss von Änderungen in deinem Arbeitsverzeichnis. W ### Branch -Ein Branch, ein Ast oder Zweig, ist im Kern ein Pointer auf den letzten Commit, den du gemacht hast. Während des Commits wird der Pointer automatisch auf Stand gebracht und zeigt dann auf den neuen letzten Commit. +Ein Branch, ein Ast oder Zweig, ist im Kern ein Pointer auf den letzten Commit, den du gemacht hast. Während des Commits wird der Pointer automatisch auf diesen Stand gebracht und zeigt dann auf den neuen letzten Commit. ### HEAD und head (Teil des .git-Verzeichnisses) @@ -215,7 +215,7 @@ $ git commit --amend -m "Correct message" ### diff -Zeigt die Unterschiede zwischen Dateien von Arbeitsverzeichnisse, dem Index und Commits an. +Zeigt die Unterschiede zwischen Dateien vom Arbeitsverzeichnis, dem Index und Commits an. ```bash # Unterschiede zwischen deinem Arbeitsverzeichnis und dem Index anzeigen @@ -330,7 +330,7 @@ $ git push origin master ### rebase (mit Vorsicht einsetzen) -Nimm alle Änderungen, die in einem Branch durch Commits vorgenommen wurden, und übertrage sie auf einen anderen Branch. Achtung: Führe keinen Rebase von Commits durch, die auf ein öffentliches Repo gepusht wurden. +Nimm alle Änderungen, die in einem Branch durch Commits vorgenommen wurden, und übertrage sie auf einen anderen Branch. Achtung: Führe keinen Rebase von Commits durch, die auf ein öffentliches Repo gepusht wurden! ```bash # Rebase "experimentBranch" in den "master"-Branch diff --git a/de-de/hq9+-de.html.markdown b/de-de/hq9+-de.html.markdown new file mode 100644 index 00000000..841de5bb --- /dev/null +++ b/de-de/hq9+-de.html.markdown @@ -0,0 +1,43 @@ +--- +language: HQ9+ +filename: hq9+-de.html +contributors: + - ["Alexey Nazaroff", "https://github.com/rogaven"] +translators: + - ["Dennis Keller", "https://github.com/denniskeller"] +lang: de-de +--- + +HQ9+ ist eine Parodie auf esoterische Programmiersprachen und wurde von Cliff Biffle kreiert. +Die Sprache hat nur vier Befehle und ist nicht Turing-vollständig. + +``` +Es gibt nur vier Befehle, die durch die folgenden vier Zeichen dargestellt werden +H: druckt "Hello, world!" +Q: druckt den Quellcode des Programms (ein Quine) +9: druckt den Liedtext von "99 Bottles of Beer" ++: erhöhe den Akkumulator um Eins (Der Wert des Akkumulators kann nicht gelesen werden) +Jedes andere Zeichen wird ignoriert. + +Ok. Lass uns ein Programm schreiben: + HQ + +Ergebnis: + Hello world! + HQ + +HQ9+ ist zwar sehr simpel, es erlaubt aber dir Sachen zu machen, die in +anderen Sprachen sehr schwierig sind. Zum Beispiel druckt das folgende Programm +drei Mal Kopien von sich selbst auf den Bildschirm: + QQQ +Dies druckt: + QQQ + QQQ + QQQ +``` + +Und das ist alles. Es gibt sehr viele Interpreter für HQ9+. +Unten findest du einen von ihnen. + ++ [One of online interpreters](https://almnet.de/esolang/hq9plus.php) ++ [HQ9+ official website](http://cliffle.com/esoterica/hq9plus.html) diff --git a/de-de/make-de.html.markdown b/de-de/make-de.html.markdown index bc5c7bcb..cf90dc29 100644 --- a/de-de/make-de.html.markdown +++ b/de-de/make-de.html.markdown @@ -1,5 +1,6 @@ ---
-language: make
+category: tool
+tool: make
contributors:
- ["Robert Steed", "https://github.com/robochat"]
- ["Stephan Fuhrmann", "https://github.com/sfuhrm"]
diff --git a/de-de/markdown-de.html.markdown b/de-de/markdown-de.html.markdown index cccf5e68..729e883c 100644 --- a/de-de/markdown-de.html.markdown +++ b/de-de/markdown-de.html.markdown @@ -144,7 +144,7 @@ indem du eine Zeile mit vier Leerzeichen oder einem Tabulator einrückst --> puts item end -<!-- Innerhalb normalen Texts kannst du Code mit Backticks ` auszeichnen --> +<!-- Innerhalb normalen Texts kannst du Code mit Backticks \` auszeichnen --> Hermann hatte nicht die leiseste Ahnung, was dieses `go_to()` bedeuten könnte! diff --git a/de-de/nix-de.html.markdown b/de-de/nix-de.html.markdown index 79b60d20..ea02e81d 100644 --- a/de-de/nix-de.html.markdown +++ b/de-de/nix-de.html.markdown @@ -8,11 +8,11 @@ translators: lang: de-de --- -Nix ist eine simple funktionale Programmiersprache, die für den +Nix ist eine simple funktionale Programmiersprache, die für den [Nix package manager](https://nixos.org/nix/) und [NixOS](https://nixos.org/) entwickelt wurde. -Du kannst Nix Ausdrücke evaluieren mithilfe von +Du kannst Nix Ausdrücke evaluieren mithilfe von [nix-instantiate](https://nixos.org/nix/manual/#sec-nix-instantiate) oder [`nix-repl`](https://github.com/edolstra/nix-repl). @@ -24,7 +24,7 @@ with builtins; [ # Inline Kommentare sehen so aus. - /* Multizeilen Kommentare + /* Multizeilen Kommentare sehen so aus. */ @@ -61,7 +61,7 @@ with builtins; [ "String Literale sind in Anführungszeichen." " - String Literale können mehrere + String Literale können mehrere Zeilen umspannen. " @@ -95,7 +95,7 @@ with builtins; [ tutorials/learn.nix #=> /the-base-path/tutorials/learn.nix - # Ein Pfad muss mindestens einen Schrägstrich enthalten. Ein Pfad für eine + # Ein Pfad muss mindestens einen Schrägstrich enthalten. Ein Pfad für eine # Datei im selben Verzeichnis benötigt ein ./ Präfix. ./learn.nix #=> /the-base-path/learn.nix @@ -238,7 +238,7 @@ with builtins; [ #=> { d = 2; e = 3; } # Die Nachkommen eines Attributs können in diesem Feld nicht zugeordnet werden, wenn - # das Attribut selbst nicht zugewiesen wurde. + # das Attribut selbst nicht zugewiesen wurde. { a = { b = 1; }; a.c = 2; @@ -261,9 +261,9 @@ with builtins; [ #=> 7 # Die erste Linie diese Tutorials startet mit "with builtins;", - # weil builtins ein Set mit allen eingebauten + # weil builtins ein Set mit allen eingebauten # Funktionen (length, head, tail, filter, etc.) umfasst. - # Das erspart uns beispielsweise "builtins.length" zu schreiben, + # Das erspart uns beispielsweise "builtins.length" zu schreiben, # anstatt nur "length". @@ -305,7 +305,7 @@ with builtins; [ (tryEval (abort "foo")) #=> error: evaluation aborted with the following error message: ‘foo’ - # `assert` evaluiert zu dem gegebenen Wert, wenn die Bedingung wahr ist, sonst + # `assert` evaluiert zu dem gegebenen Wert, wenn die Bedingung wahr ist, sonst # löst es eine abfangbare Exception aus. (assert 1 < 2; 42) #=> 42 @@ -319,7 +319,7 @@ with builtins; [ #========================================= # Da die Wiederholbarkeit von Builds für den Nix Packetmanager entscheidend ist, - # werden in der Nix Sprache reine funktionale Elemente betont. Es gibt aber ein paar + # werden in der Nix Sprache reine funktionale Elemente betont. Es gibt aber ein paar # unreine Elemente. # Du kannst auf Umgebungsvariablen verweisen. (getEnv "HOME") @@ -355,4 +355,4 @@ with builtins; [ (https://medium.com/@MrJamesFisher/nix-by-example-a0063a1a4c55) * [Susan Potter - Nix Cookbook - Nix By Example] - (http://funops.co/nix-cookbook/nix-by-example/) + (https://ops.functionalalgebra.com/nix-by-example/) diff --git a/de-de/opencv-de.html.markdown b/de-de/opencv-de.html.markdown new file mode 100644 index 00000000..223e6cd8 --- /dev/null +++ b/de-de/opencv-de.html.markdown @@ -0,0 +1,153 @@ +--- +category: tool +tool: OpenCV +filename: learnopencv-de.py +contributors: + - ["Yogesh Ojha", "http://github.com/yogeshojha"] +translators: + - ["Dennis Keller", "https://github.com/denniskeller"] +lang: de-de +--- +### Opencv + +OpenCV (Open Source Computer Vision) ist eine Bibliothek von Programmierfunktionen, +die hauptsächlich auf maschinelles Sehen in Echtzeit ausgerichtet ist. +Ursprünglich wurde OpenCV von Intel entwickelt. Später wurde es von von +Willow Garage und dann Itseez (das später von Intel übernommen wurde) unterstützt. +OpenCV unterstützt derzeit eine Vielzahl von Sprachen, wie C++, Python, Java uvm. + +#### Installation + +Bitte lese diese Artikel für die Installation von OpenCV auf deinen Computer. + +* Windows Installationsanleitung: [https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_setup/py_setup_in_windows/py_setup_in_windows.html#install-opencv-python-in-windows]() +* Mac Installationsanleitung (High Sierra): [https://medium.com/@nuwanprabhath/installing-opencv-in-macos-high-sierra-for-python-3-89c79f0a246a]() +* Linux Installationsanleitung (Ubuntu 18.04): [https://www.pyimagesearch.com/2018/05/28/ubuntu-18-04-how-to-install-opencv]() + +### Hier werden wir uns auf die Pythonimplementierung von OpenCV konzentrieren. + +```python +# Bild in OpenCV lesen +import cv2 +img = cv2.imread('Katze.jpg') + +# Bild darstellen +# Die imshow() Funktion wird verwendet um das Display darzustellen. +cv2.imshow('Image',img) +# Das erste Argument ist der Titel des Fensters und der zweite Parameter ist das Bild +# Wenn du den Fehler Object Type None bekommst ist eventuell dein Bildpfad falsch. +# Bitte überprüfe dann den Pfad des Bildes erneut. +cv2.waitKey(0) +# waitKey() ist eine Tastaturbindungsfunktion, sie nimmt Argumente in +# Millisekunden an. Für GUI Ereignisse MUSST du die waitKey() Funktion verwenden. + +# Ein Bild schreiben +cv2.imwrite('graueKatze.png',img) +# Das erste Arkument ist der Dateiname und das Zweite ist das Bild + +# Konveriere das Bild zu Graustufen +gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) + +# Videoaufnahme von der Webcam +cap = cv2.VideoCapture(0) +# 0 ist deine Kamera, wenn du mehrere Kameras hast musst du deren Id eingeben +while(True): + # Erfassen von Einzelbildern + _, frame = cap.read() + cv2.imshow('Frame',frame) + # Wenn der Benutzer q drückt -> beenden + if cv2.waitKey(1) & 0xFF == ord('q'): + break +# Die Kamera muss wieder freigegeben werden +cap.release() + +# Wiedergabe von Videos aus einer Datei +cap = cv2.VideoCapture('film.mp4') +while(cap.isOpened()): + _, frame = cap.read() + # Das Video in Graustufen abspielen + gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) + cv2.imshow('frame',gray) + if cv2.waitKey(1) & 0xFF == ord('q'): + break +cap.release() + +# Zeichne eine Linie in OpenCV +# cv2.line(img,(x,y),(x1,y1),(color->r,g,b->0 to 255),thickness) +cv2.line(img,(0,0),(511,511),(255,0,0),5) + +# Zeichne ein Rechteck +# cv2.rectangle(img,(x,y),(x1,y1),(color->r,g,b->0 to 255),thickness) +# thickness = -1 wird zum Füllen des Rechtecks verwendet +cv2.rectangle(img,(384,0),(510,128),(0,255,0),3) + +# Zeichne ein Kreis +cv2.circle(img,(xCenter,yCenter), radius, (color->r,g,b->0 to 255), thickness) +cv2.circle(img,(200,90), 100, (0,0,255), -1) + +# Zeichne eine Ellipse +cv2.ellipse(img,(256,256),(100,50),0,0,180,255,-1) + +# Text auf Bildern hinzufügen +cv2.putText(img,"Hello World!!!", (x,y), cv2.FONT_HERSHEY_SIMPLEX, 2, 255) + +# Bilder zusammenfüggen +img1 = cv2.imread('Katze.png') +img2 = cv2.imread('openCV.jpg') +dst = cv2.addWeighted(img1,0.5,img2,0.5,0) + +# Schwellwertbild +# Binäre Schwellenwerte +_,thresImg = cv2.threshold(img,127,255,cv2.THRESH_BINARY) +# Anpassbare Schwellenwerte +adapThres = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY,11,2) + +# Weichzeichnung von einem Bild +# Gausßscher Weichzeichner +blur = cv2.GaussianBlur(img,(5,5),0) +# Rangordnungsfilter +medianBlur = cv2.medianBlur(img,5) + +# Canny-Algorithmus +img = cv2.imread('Katze.jpg',0) +edges = cv2.Canny(img,100,200) + +# Gesichtserkennung mit Haarkaskaden +# Lade die Haarkaskaden von https://github.com/opencv/opencv/blob/master/data/haarcascades/ herunter +import cv2 +import numpy as np +face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml') +eye_cascade = cv2.CascadeClassifier('haarcascade_eye.xml') + +img = cv2.imread('Mensch.jpg') +gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) + +aces = face_cascade.detectMultiScale(gray, 1.3, 5) +for (x,y,w,h) in faces: + cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) + roi_gray = gray[y:y+h, x:x+w] + roi_color = img[y:y+h, x:x+w] + eyes = eye_cascade.detectMultiScale(roi_gray) + for (ex,ey,ew,eh) in eyes: + cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,0),2) + +cv2.imshow('img',img) +cv2.waitKey(0) + +cv2.destroyAllWindows() +# destroyAllWindows() zerstört alle Fenster +# Wenn du ein bestimmtes Fenter zerstören möchtest musst du den genauen Namen des +# von dir erstellten Fensters übergeben. +``` + +### Weiterführende Literatur: +* Lade Kaskade hier herunter [https://github.com/opencv/opencv/blob/master/data/haarcascades]() +* OpenCV Zeichenfunktionen [https://docs.opencv.org/2.4/modules/core/doc/drawing_functions.html]() +* Eine aktuelle Sprachenreferenz kann hier gefunden werden [https://opencv.org]() +* Zusätzliche Ressourcen können hier gefunden werden [https://en.wikipedia.org/wiki/OpenCV]() +* Gute OpenCV Tutorials + * [https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_tutorials.html]() + * [https://realpython.com/python-opencv-color-spaces]() + * [https://pyimagesearch.com]() + * [https://www.learnopencv.com]() + * [https://docs.opencv.org/master/]() diff --git a/de-de/paren-de.html.markdown b/de-de/paren-de.html.markdown new file mode 100644 index 00000000..641e226e --- /dev/null +++ b/de-de/paren-de.html.markdown @@ -0,0 +1,200 @@ +--- + +language: Paren +filename: learnparen-de.paren +contributors: + - ["KIM Taegyoon", "https://github.com/kimtg"] + - ["Claudson Martins", "https://github.com/claudsonm"] +translators: + - ["Dennis Keller", "https://github.com/denniskeller"] +lang: de-de +--- + +[Paren](https://bitbucket.org/ktg/paren) ist ein Dialekt von Lisp. +Es ist als eingebettete Sprache konzipiert. + +Manche Beispiele sind von <http://learnxinyminutes.com/docs/racket/>. + +```scheme +;;; Kommentare +# Kommentare + +;; Einzeilige Kommentare starten mit einem Semikolon oder einem Hashtag + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 1. Primitive Datentypen und Operatoren +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; Zahlen +123 ; int +3.14 ; double +6.02e+23 ; double +(int 3.14) ; => 3 : int +(double 123) ; => 123 : double + +;; Funktionsapplikationen werden so geschrieben: (f x y z ...) +;; Dabei ist f eine Funktion und x, y, z sind die Operatoren. +;; Wenn du eine Literalliste von Daten erstelllen möchtest, +;; verwende (quote) um zu verhindern, dass sie ausgewertet zu werden. +(quote (+ 1 2)) ; => (+ 1 2) +;; Nun einige arithmetische Operationen +(+ 1 1) ; => 2 +(- 8 1) ; => 7 +(* 10 2) ; => 20 +(^ 2 3) ; => 8 +(/ 5 2) ; => 2 +(% 5 2) ; => 1 +(/ 5.0 2) ; => 2.5 + +;;; Wahrheitswerte +true ; for Wahr +false ; for Falsch +(! true) ; => Falsch +(&& true false (prn "doesn't get here")) ; => Falsch +(|| false true (prn "doesn't get here")) ; => Wahr + +;;; Zeichen sind Ints. +(char-at "A" 0) ; => 65 +(chr 65) ; => "A" + +;;; Zeichenketten sind ein Array von Zahlen mit fester Länge. +"Hello, world!" +"Benjamin \"Bugsy\" Siegel" ; Backslash ist ein Escape-Zeichen +"Foo\tbar\r\n" ; beinhaltet C Escapes: \t \r \n + +;; Zeichenketten können auch verbunden werden! +(strcat "Hello " "world!") ; => "Hello world!" + +;; Eine Zeichenketten kann als Liste von Zeichen behandelt werden +(char-at "Apple" 0) ; => 65 + +;; Drucken ist ziemlich einfach +(pr "Ich bin" "Paren. ") (prn "Schön dich zu treffen!") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 2. Variablen +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Du kannst Variablen setzen indem du (set) verwedest +;; eine Variable kann alle Zeichen besitzen außer: ();#" +(set some-var 5) ; => 5 +some-var ; => 5 + +;; Zugriff auf eine zuvor nicht zugewiesene Variable erzeugt eine Ausnahme +; x ; => Unknown variable: x : nil + +;; Lokale Bindung: Verwende das Lambda Calculus! 'a' und 'b' +;; sind nur zu '1' und '2' innerhalb von (fn ...) gebunden. +((fn (a b) (+ a b)) 1 2) ; => 3 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 3. Sammlungen +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; Listen + +;; Listen sind Vektrorartige Datenstrukturen. (Zufälliger Zugriff ist O(1). +(cons 1 (cons 2 (cons 3 (list)))) ; => (1 2 3) +;; 'list' ist ein komfortabler variadischer Konstruktor für Listen +(list 1 2 3) ; => (1 2 3) +;; und ein quote kann als literaler Listwert verwendet werden +(quote (+ 1 2)) ; => (+ 1 2) + +;; Du kannst 'cons' verwenden um ein Element an den Anfang einer Liste hinzuzufügen. +(cons 0 (list 1 2 3)) ; => (0 1 2 3) + +;; Listen sind ein sehr einfacher Typ, daher gibt es eine Vielzahl an Funktionen +;; für Sie. Ein paar Beispiele: +(map inc (list 1 2 3)) ; => (2 3 4) +(filter (fn (x) (== 0 (% x 2))) (list 1 2 3 4)) ; => (2 4) +(length (list 1 2 3 4)) ; => 4 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 3. Funktionen +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Verwende 'fn' um Funktionen zu erstellen. +;; eine Funktion gibt immer den Wert ihres letzten Ausdrucks zurück +(fn () "Hello World") ; => (fn () Hello World) : fn + +;; Verwende Klammern um alle Funktionen aufzurufen, inklusive Lambda Ausdrücke +((fn () "Hello World")) ; => "Hello World" + +;; Zuweisung einer Funktion zu einer Variablen +(set hello-world (fn () "Hello World")) +(hello-world) ; => "Hello World" + +;; Du kannst dies mit syntaktischen Zucker für die Funktionsdefinition verkürzen: +(defn hello-world2 () "Hello World") + +;; Die () von oben ist eine Liste von Argumente für die Funktion. +(set hello + (fn (name) + (strcat "Hello " name))) +(hello "Steve") ; => "Hello Steve" + +;; ... oder gleichwertig, unter Verwendung mit syntaktischen Zucker: +(defn hello2 (name) + (strcat "Hello " name)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 4. Gleichheit +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Für Zahlen verwende '==' +(== 3 3.0) ; => wahr +(== 2 1) ; => falsch + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 5. Kontrollfluss +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; Bedingungen + +(if true ; test Ausdruck + "this is true" ; then Ausdruck + "this is false") ; else Ausdruck +; => "this is true" + +;;; Schleifen + +;; for Schleifen ist für Zahlen +;; (for SYMBOL START ENDE SCHRITT AUSDRUCK ..) +(for i 0 10 2 (pr i "")) ; => schreibt 0 2 4 6 8 10 +(for i 0.0 10 2.5 (pr i "")) ; => schreibt 0 2.5 5 7.5 10 + +;; while Schleife +((fn (i) + (while (< i 10) + (pr i) + (++ i))) 0) ; => schreibt 0123456789 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 6. Mutation +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Verwende 'set' um einer Variablen oder einer Stelle einen neuen Wert zuzuweisen. +(set n 5) ; => 5 +(set n (inc n)) ; => 6 +n ; => 6 +(set a (list 1 2)) ; => (1 2) +(set (nth 0 a) 3) ; => 3 +a ; => (3 2) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 7. Makros +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Makros erlauben es dir die Syntax der Sprache zu erweitern. +;; Parens Makros sind einfach. +;; Tatsächlich ist (defn) ein Makro. +(defmacro setfn (name ...) (set name (fn ...))) +(defmacro defn (name ...) (def name (fn ...))) + +;; Lass uns eine Infix Notation hinzufügen +;; Let's add an infix notation +(defmacro infix (a op ...) (op a ...)) +(infix 1 + 2 (infix 3 * 4)) ; => 15 + +;; Makros sind nicht hygenisch, Du kannst bestehende Variablen überschreiben! +;; Sie sind Codetransformationenen. +``` diff --git a/de-de/python-de.html.markdown b/de-de/python-de.html.markdown index ae29d6f9..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. Klassen +## 5. Module #################################################### -# Wir bilden die Unterklasse eines Objekts, um Klassen zu erhalten. +# 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. + + +#################################################### +## 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 + # 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 +## 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 :( ``` diff --git a/de-de/python3-de.html.markdown b/de-de/python3-de.html.markdown index 33897225..4ef997a1 100644 --- a/de-de/python3-de.html.markdown +++ b/de-de/python3-de.html.markdown @@ -14,7 +14,7 @@ Python wurde in den frühen Neunzigern von Guido van Rossum entworfen. Es ist he Feedback ist herzlich willkommen! Ihr erreicht mich unter [@louiedinh](http://twitter.com/louiedinh) oder louiedinh [at] [google's email service]. -Hinweis: Dieser Beitrag bezieht sich insplizit auf Python 3. Falls du lieber Python 2.7 lernen möchtest, schau [hier](http://learnxinyminutes.com/docs/python/) weiter. +Hinweis: Dieser Beitrag bezieht sich implizit auf Python 3. Falls du lieber Python 2.7 lernen möchtest, schau [hier](http://learnxinyminutes.com/docs/python/) weiter. ```python @@ -152,7 +152,7 @@ print("Ich bin Python. Schön, dich kennenzulernen!") some_var = 5 # kleinschreibung_mit_unterstrichen entspricht der Norm some_var #=> 5 -# Das Ansprechen einer noch nicht deklarierte Variable löst eine Exception aus. +# Das Ansprechen einer noch nicht deklarierten Variable löst eine Exception aus. # Unter "Kontrollstruktur" kann noch mehr über # Ausnahmebehandlung erfahren werden. some_unknown_var # Löst einen NameError aus @@ -225,7 +225,7 @@ a, b, c = (1, 2, 3) # a ist jetzt 1, b ist jetzt 2 und c ist jetzt 3 # Tupel werden standardmäßig erstellt, wenn wir uns die Klammern sparen d, e, f = 4, 5, 6 # Es ist kinderleicht zwei Werte zu tauschen -e, d = d, e # d is now 5 and e is now 4 +e, d = d, e # d ist nun 5 und e ist nun 4 # Dictionarys (Wörterbucher) speichern Schlüssel-Werte-Paare @@ -379,8 +379,8 @@ with open("meineDatei.txt") as f: print(line) # Python bietet ein fundamentales Konzept der Iteration. -# Das Objekt, auf das die Interation, also die Wiederholung einer Methode angewandt wird heißt auf Englisch "iterable". -# Die range Method gibt ein solches Objekt aus. +# Das Objekt, auf das die Iteration, also die Wiederholung einer Methode angewandt wird heißt auf Englisch "iterable". +# Die range Methode gibt ein solches Objekt aus. filled_dict = {"one": 1, "two": 2, "three": 3} our_iterable = filled_dict.keys() @@ -396,8 +396,8 @@ our_iterable[1] # TypeError # Ein iterable ist ein Objekt, das weiß wie es einen Iteratoren erschafft. our_iterator = iter(our_iterable) -# Unser Iterator ist ein Objekt, das sich merkt, welchen Status es geraden hat während wir durch es gehen. -# Das jeweeils nächste Objekt bekommen wir mit "next()" +# Unser Iterator ist ein Objekt, das sich merkt, welchen Status es gerade hat während wir durch es gehen. +# Das jeweils nächste Objekt bekommen wir mit "next()" next(our_iterator) #=> "one" # Es hält den vorherigen Status @@ -442,7 +442,7 @@ def keyword_args(**kwargs): # Rufen wir es mal auf, um zu sehen, was passiert keyword_args(big="foot", loch="ness") #=> {"big": "foot", "loch": "ness"} -# Wir können beides gleichzeitig machem, wenn wir wollen +# Wir können beides gleichzeitig machen, wenn wir wollen def all_the_args(*args, **kwargs): print(args) print(kwargs) @@ -555,7 +555,7 @@ Human.grunt() #=> "*grunt*" # Wir können Module importieren import math -print(math.sqrt(16)) #=> 4 +print(math.sqrt(16)) #=> 4.0 # Wir können auch nur spezielle Funktionen eines Moduls importieren from math import ceil, floor diff --git a/de-de/rst-de.html.markdown b/de-de/rst-de.html.markdown new file mode 100644 index 00000000..072299f5 --- /dev/null +++ b/de-de/rst-de.html.markdown @@ -0,0 +1,119 @@ +--- +language: restructured text (RST) +filename: restructuredtext-de.rst +contributors: + - ["DamienVGN", "https://github.com/martin-damien"] + - ["Andre Polykanine", "https://github.com/Oire"] +translators: + - ["Dennis Keller", "https://github.com/denniskeller"] +lang: de-de +--- + +RST ist ein Dateiformat, das von der Python Community entwickelt wurde, + +um Dokumentation zu schreiben (und ist somit Teil von Docutils). + +RST-Dateien sind simple Textdateien mit einer leichtgewichtigen Syntax (im Vergleich zu HTML). + + +## Installation + +Um Restructured Text zu vewenden musst du [Python](http://www.python.org) + +installieren und das `docutils` Packet installieren. `docutils` kann mit dem folgenden + +Befehl auf der Kommandozeile installiert werden: + +```bash +$ easy_install docutils +``` + +Wenn auf deinem System `pip` installiert kannst du es statdessen auch verwenden: + +```bash +$ pip install docutils +``` + + +## Dateisyntax + +Ein einfaches Beispiel für die Dateisyntax: + +``` +.. Zeilen, die mit zwei Punkten starten sind spezielle Befehle. + +.. Wenn kein Befehl gefunden wird, wird die Zeile als Kommentar gewertet. + +============================================================================ +Haupttitel werden mit Gleichheitszeichen darüber und darunter gekennzeichnet +============================================================================ + +Beachte das es genau so viele Gleichheitszeichen, wie Hauptitelzeichen +geben muss. + +Titel werden auch mit Gleichheitszeichen unterstrichen +====================================================== + +Untertitel werden mit Strichen gekennzeichnet +--------------------------------------------- + +Text in *kursiv* oder in **fett**. Du kannst Text als Code "makieren", wenn +du doppelte Backquotes verwendest ``: ``print()``. + +Listen sind so einfach wie in Markdown: + +- Erstes Element +- Zweites Element + - Unterelement + +oder + +* Erstes Element +* Zweites Element + * Unterelement + +Tabellen sind einfach zu schreiben: + +=========== ========== +Land Hauptstadt +=========== ========== +Frankreich Paris +Japan Tokyo +=========== ======== + +Komplexere Tabellen (zusammengeführte Spalten und Zeilen) können einfach +erstellt werden, aber ich empfehle dir dafür die komplette Dokumentation zu lesen :) + +Es gibt mehrere Möglichkeiten um Links zu machen: + +- Wenn man einen Unterstrich hinter einem Wort hinzufügt: Github_ Zusätzlich +muss man die Zielurl nach dem Text hinzufügen. +(Dies hat den Vorteil, dass man keine unnötigen Urls in lesbaren Text einfügt. +- Wenn man die vollständige Url eingibt : https://github.com/ +(Dies wird automatisch in ein Link konvertiert.) +- Wenn man es mehr Markdown ähnlich eingibt: `Github <https://github.com/>`_ . + +.. _Github https://github.com/ + +``` + + +## Wie man es verwendet + +RST kommt mit docutils, dort hast du den Befehl `rst2html`, zum Beispiel: + +```bash +$ rst2html myfile.rst output.html +``` + +*Anmerkung : Auf manchen Systemen könnte es rst2html.py sein* + +Es gibt komplexere Anwendungen, die das RST Format verwenden: + +- [Pelican](http://blog.getpelican.com/), ein statischer Websitengenerator +- [Sphinx](http://sphinx-doc.org/), Ein Dokumentationsgenerator +- und viele Andere + +## Zum Lesen + +- [Offizielle Schnellreferenz](http://docutils.sourceforge.net/docs/user/rst/quickref.html) diff --git a/de-de/shutit-de.html.markdown b/de-de/shutit-de.html.markdown new file mode 100644 index 00000000..29ed639e --- /dev/null +++ b/de-de/shutit-de.html.markdown @@ -0,0 +1,330 @@ +--- +category: tool +filename: learnshutit-de.html +tool: ShutIt +contributors: + - ["Ian Miell", "http://ian.meirionconsulting.tk"] +translators: + - ["Dennis Keller", "https://github.com/denniskeller"] +lang: de-de +--- + +## ShutIt + +ShuIt ist eine Shellautomationsframework, welches für eine einfache +Handhabung entwickelt wurde. + +Er ist ein Wrapper, der auf einem Python expect Klon (pexpect) basiert. + +Es ist damit ein 'expect ohne Schmerzen'. + +Es ist verfügbar als pip install. + +## Hello World + +Starten wir mit dem einfachsten Beispiel. Erstelle eine Datei names example.py + +```python + +import shutit +session = shutit.create_session('bash') +session.send('echo Hello World', echo=True) +``` + +Führe es hiermit aus: + +```bash +python example.py +``` + +gibt aus: + +```bash +$ python example.py +echo "Hello World" +echo "Hello World" +Hello World +Ians-MacBook-Air.local:ORIGIN_ENV:RhuebR2T# +``` + +Das erste Argument zu 'send' ist der Befehl, den du ausführen möchtest. +Das 'echo' Argument gibt die Terminalinteraktion aus. ShuIt ist standardmäßig leise. + +'Send' kümmert sich um die nervige Arbeiten mit den Prompts und macht +alles was du von 'expect' erwarten würdest. + + +## Logge dich auf einen Server ein + +Sagen wir du möchtest dich auf einen Server einloggen und einen Befehl ausführen. +Ändere dafür example.py folgendermaßen: + +```python +import shutit +session = shutit.create_session('bash') +session.login('ssh you@example.com', user='du', password='meinpassword') +session.send('hostname', echo=True) +session.logout() +``` + +Dies erlaubt dir dich auf deinen Server einzuloggen +(ersetze die Details mit deinen Eigenen) und das Programm gibt dir deinen Hostnamen aus. + +``` +$ python example.py +hostname +hostname +example.com +example.com:cgoIsdVv:heDa77HB# +``` + + +Es ist klar das das nicht sicher ist. Stattdessen kann man Folgendes machen: + +```python +import shutit +session = shutit.create_session('bash') +password = session.get_input('', ispass=True) +session.login('ssh you@example.com', user='du', password=password) +session.send('hostname', echo=True) +session.logout() +``` + +Dies zwingt dich dein Passwort einzugeben: + +``` +$ python example.py +Input Secret: +hostname +hostname +example.com +example.com:cgoIsdVv:heDa77HB# +``` + + +Die 'login' Methode übernimmt wieder das veränderte Prompt für den Login. +Du übergibst ShutIt den User und das Passwort, falls es benötigt wird, +mit den du dich einloggen möchtest. ShutIt übernimmt den Rest. + +'logout' behandelt das Ende von 'login' und übernimmt alle Veränderungen des +Prompts für dich. + +## Einloggen auf mehrere Server + +Sagen wir, dass du eine Serverfarm mit zwei Servern hast und du dich in +beide Server einloggen möchtest. Dafür musst du nur zwei Session und +Logins erstellen und kannst dann Befehle schicken: + +```python +import shutit +session1 = shutit.create_session('bash') +session2 = shutit.create_session('bash') +password1 = session1.get_input('Password für server1', ispass=True) +password2 = session2.get_input('Password für server2', ispass=True) +session1.login('ssh you@one.example.com', user='du', password=password1) +session2.login('ssh you@two.example.com', user='du', password=password2) +session1.send('hostname', echo=True) +session2.send('hostname', echo=True) +session1.logout() +session2.logout() +``` + +Gibt aus: + +```bash +$ python example.py +Password for server1 +Input Secret: + +Password for server2 +Input Secret: +hostname +hostname +one.example.com +one.example.com:Fnh2pyFj:qkrsmUNs# hostname +hostname +two.example.com +two.example.com:Gl2lldEo:D3FavQjA# +``` + +## Beispiel: Überwachen mehrerer Server + +Wir können das obige Programm in ein einfaches Überwachungstool bringen indem +wir Logik hinzufügen um die Ausgabe von einem Befehl zu betrachten. + +```python +import shutit +capacity_command="""df / | awk '{print $5}' | tail -1 | sed s/[^0-9]//""" +session1 = shutit.create_session('bash') +session2 = shutit.create_session('bash') +password1 = session.get_input('Passwort für Server1', ispass=True) +password2 = session.get_input('Passwort für Server2', ispass=True) +session1.login('ssh you@one.example.com', user='du', password=password1) +session2.login('ssh you@two.example.com', user='du', password=password2) +capacity = session1.send_and_get_output(capacity_command) +if int(capacity) < 10: + print(kein Platz mehr auf Server1!') +capacity = session2.send_and_get_output(capacity_command) +if int(capacity) < 10: + print(kein Platz mehr auf Server2!') +session1.logout() +session2.logout() +``` + +Hier kannst du die 'send\_and\_get\_output' Methode verwenden um die Ausgabe von dem +Kapazitätsbefehl (df) zu erhalten. + +Es gibt elegantere Wege als oben (z.B. kannst du ein Dictionary verwenden um über +die Server zu iterieren), aber es hängt and dir wie clever das Python sein muss. + + +## kompliziertere IO - Expecting + +Sagen wir du hast eine Interaktion mit einer interaktiven Kommandozeilenprogramm, +die du automatisieren möchtest. Hier werden wir Telnet als triviales Beispiel verwenden: + +```python +import shutit +session = shutit.create_session('bash') +session.send('telnet', expect='elnet>', echo=True) +session.send('open google.com 80', expect='scape character', echo=True) +session.send('GET /', echo=True, check_exit=False) +session.logout() +``` + +Beachte das 'expect' Argument. Du brauchst nur ein Subset von Telnets +Eingabeaufforderung um es abzugleichen und fortzufahren. + +Beachte auch das neue Argument 'check\_exit'. Wir werden nachher nochmal +darauf zurückkommen. Die Ausgabe von oben ist: + +```bash +$ python example.py +telnet +telnet> open google.com 80 +Trying 216.58.214.14... +Connected to google.com. +Escape character is '^]'. +GET / +HTTP/1.0 302 Found +Cache-Control: private +Content-Type: text/html; charset=UTF-8 +Referrer-Policy: no-referrer +Location: http://www.google.co.uk/?gfe_rd=cr&ei=huczWcj3GfTW8gfq0paQDA +Content-Length: 261 +Date: Sun, 04 Jun 2017 10:57:10 GMT + +<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8"> +<TITLE>302 Moved</TITLE></HEAD><BODY> +<H1>302 Moved</H1> +The document has moved +<A HREF="http://www.google.co.uk/?gfe_rd=cr&ei=huczWcj3GfTW8gfq0paQDA"> +here +</A>. +</BODY></HTML> +Connection closed by foreign host. +``` + +Nun zurück zu 'check\_exit=False'. Da das Telnet Programm einen Fehler mit +Fehlercode (1) zurückgibt und wir nicht möchten das das Skript fehlschlägt +kannst du 'check\_exit=False' setzen und damit ShuIt wissen lassen, dass +der Ausgabecode dich nicht interessiert. + +Wenn du das Argument nicht mitgegeben hättest, dann hätte dir ShutIt +ein interaktives Terminal zurückgegeben, falls es ein Terminal zum +kommunizieren gibt. Dies nennt sich ein 'Pause point'. + + +## Pause Points + +Du kannst jederzeit 'pause point' auslösen, wenn du Folgendes in deinem Skript aufrufst: + +```python +[...] +session.pause_point('Das ist ein pause point') +[...] +``` + +Danach kannst du das Skript fortführen, wenn du CTRL und ']' zur selben Zeit drückst. +Dies ist gut für Debugging: Füge ein Pause Point hinzu und schaue dich um. +Danach kannst du das Programm weiter ausführen. Probiere folgendes aus: + +```python +import shutit +session = shutit.create_session('bash') +session.pause_point('Schaue dich um!') +session.send('echo "Hat dir der Pause point gefallen?"', echo=True) +``` + +Dies würde folgendes ausgeben: + +```bash +$ python example.py +Schaue dich um! + +Ians-Air.home:ORIGIN_ENV:I00LA1Mq# bash +imiell@Ians-Air:/space/git/shutit ⑂ master + +CTRL-] caught, continuing with run... +2017-06-05 15:12:33,577 INFO: Sending: exit +2017-06-05 15:12:33,633 INFO: Output (squashed): exitexitIans-Air.home:ORIGIN_ENV:I00LA1Mq# [...] +echo "Hat dir der Pause point gefallen?" +echo "Hat dir der Pause point gefallen?" +Hat dir der Pause point gefallen? +Ians-Air.home:ORIGIN_ENV:I00LA1Mq# +``` + + +## noch kompliziertere IO - Hintergrund + +Kehren wir zu unseren Beispiel mit dem Überwachen von mehreren Servern zurück. +Stellen wir uns vor, dass wir eine langlaufende Aufgabe auf jedem Server durchführen möchten. +Standardmäßig arbeitet ShutIt seriell, was sehr lange dauern würde. +Wir können jedoch die Aufgaben im Hintergrund laufen lassen um sie zu beschleunigen. + +Hier ist ein Beispiel, welches du ausprobieren kannst. +Es verwendet den trivialen Befehl: 'sleep'. + + +```python +import shutit +import time +long_command="""sleep 60""" +session1 = shutit.create_session('bash') +session2 = shutit.create_session('bash') +password1 = session1.get_input('Password for server1', ispass=True) +password2 = session2.get_input('Password for server2', ispass=True) +session1.login('ssh you@one.example.com', user='du', password=password1) +session2.login('ssh you@two.example.com', user='du', password=password2) +start = time.time() +session1.send(long_command, background=True) +session2.send(long_command, background=True) +print('Es hat: ' + str(time.time() - start) + ' Sekunden zum Starten gebraucht') +session1.wait() +session2.wait() +print('Es hat:' + str(time.time() - start) + ' Sekunden zum Vollenden gebraucht') +``` + +Mein Computer meint, dass er 0.5 Sekunden gebraucht hat um die Befehle zu starten +und dann nur etwas über eine Minute gebraucht um sie zu beenden +(mit Verwendung der 'wait' Methode). + + +Das alles ist trivial, aber stelle dir vor das du hunderte an Servern so managen +kannst und man kann nun das Potential sehen, die in ein paar Zeilen Code und ein Python +import liegen können. + + +## Lerne mehr + +Es gibt noch viel mehr, was mit ShutIt erreicht werden kann. + +Um mehr zu erfahren, siehe: + +[ShutIt](https://ianmiell.github.io/shutit/) +[GitHub](https://github.com/ianmiell/shutit/blob/master/README.md) + +Es handelt sich um ein breiteres Automatiesierungsframework, und das oben +genannte ist der sogennante 'standalone Modus'. + +Feedback, feature requests, 'Wie mache ich es' sind herzlich willkommen! Erreiche mit unter +[@ianmiell](https://twitter.com/ianmiell) diff --git a/de-de/yaml-de.html.markdown b/de-de/yaml-de.html.markdown index 25f2edc4..ff45dc8d 100644 --- a/de-de/yaml-de.html.markdown +++ b/de-de/yaml-de.html.markdown @@ -10,7 +10,7 @@ lang: de-de YAML ist eine Sprache zur Datenserialisierung, die sofort von Menschenhand geschrieben und gelesen werden kann. -YAML ist ein Erweiterung von von JSON mit der Erweiterung um syntaktisch wichtige Zeilenumbrüche und Einrückungen, ähnlich wie auch in Python. Anders als in Python allerdings erlaubt YAML keine Tabulator-Zeichen. +YAML ist ein Erweiterung von JSON mit der Erweiterung um syntaktisch wichtige Zeilenumbrüche und Einrückungen, ähnlich wie auch in Python geschrieben werden können. Anders als in Python allerdings erlaubt YAML keine Tabulator-Zeichen. ```yaml # Kommentare in YAML schauen so aus. @@ -111,7 +111,7 @@ python_komplexe_Zahlen: !!python/komplex 1+2j # EXTRA YAML TYPEN # #################### -# Strings and Zahlen sind nicht die einzigen Skalare, welche YAML versteht. +# Strings und Zahlen sind nicht die einzigen Skalare, welche YAML versteht. # ISO-formatierte Datumsangaben and Zeiangaben können ebenso geparsed werden. DatumZeit: 2001-12-15T02:59:43.1Z DatumZeit_mit_Leerzeichen: 2001-12-14 21:59:43.10 -5 |