Mittwoch, 12. November 2014
Mini-Vergleich von Programmiersprachen
Als Beispiel kommt "99 bottles of beer" zum Einsatz. Die Programme stammen von http://99-bottles-of-beer.net/ und dienen eigentlich nur als Beispiele, um die Code-Struktur kleinerer Programme zu sehen.
Python
Python unterstützt mehrere Programmierparadigmen. So werden objektorientierte, aspektorientierte und funktionale Programmierung unterstützt. Wie andere dynamische Sprachen wird Python oft als Skriptsprache genutzt.
"""
99 bottles of beer in Python
"""
for quant in range(99, 0, -1):
if quant > 1:
print(quant, "bottles of beer on the wall,", quant, "bottles of beer.")
if quant > 2:
suffix = str(quant - 1) + " bottles of beer on the wall."
else:
suffix = "1 bottle of beer on the wall."
elif quant == 1:
print("1 bottle of beer on the wall, 1 bottle of beer.")
suffix = "no more beer on the wall!"
print("Take one down, pass it around,", suffix)
print("--")
Hier die Python Lösung zum Ausführen
Java
Java ist eine objektorientierte Programmiersprache und eine eingetragene Marke des Unternehmens Sun Microsystems (seit 2010 Oracle). Die Programmiersprache ist ein Bestandteil der Java-Technologie – diese besteht grundsätzlich aus dem Java-Entwicklungswerkzeug (JDK) zum Erstellen von Java-Programmen und der Java-Laufzeitumgebung (JRE) zu deren Ausführung. Die Laufzeitumgebung besteht selbst aus der virtuellen Maschine (JVM) sowie den mitgelieferten Bibliotheken der Java-Laufzeitumgebung.
/*
* 99 bottles of beer in Java
*/
class bottles {
public static void main(String args[]) {
String s = "s";
for (int beers=99; beers>-1;) {
System.out.print(beers + " bottle" + s + " of beer on the wall, ");
System.out.println(beers + " bottle" + s + " of beer, ");
if (beers==0) {
System.out.print("Go to the store, buy some more, ");
System.out.println("99 bottles of beer on the wall.\n");
System.exit(0);
} else
System.out.print("Take one down, pass it around, ");
s = (--beers == 1)?"":"s";
System.out.println(beers + " bottle" + s + " of beer on the wall.\n");
}
}
}
C
C ist eine imperative Programmiersprache, die der Informatiker Dennis Ritchie in den frühen 1970er Jahren an den Bell Laboratories für die Systemprogrammierung des Betriebssystems Unix entwickelte. Seitdem ist sie auf vielen Computersystemen verbreitet. Die Anwendungsbereiche von C sind sehr verschieden. Sie wird zur System- und Anwendungsprogrammierung eingesetzt. Die grundlegenden Programme aller Unix-Systeme und die Systemkerne vieler Betriebssysteme sind in C programmiert. Zahlreiche Sprachen, wie C++, Objective-C, C#, Java, PHP, Vala oder Perl orientieren sich an der Syntax und anderen Eigenschaften von C.
/*
* 99 bottles of beer in C
*/
#define MAXBEER (99)
void chug(int beers);
main()
{
register beers;
for(beers = MAXBEER; beers; chug(beers--))
puts("");
puts("\nTime to buy more beer!\n");
exit(0);
}
void chug(register beers)
{
char howmany[8], *s;
s = beers != 1 ? "s" : "";
printf("%d bottle%s of beer on the wall,\n", beers, s);
printf("%d bottle%s of beeeeer . . . ,\n", beers, s);
printf("Take one down, pass it around,\n");
if(--beers) sprintf(howmany, "%d", beers); else strcpy(howmany, "No more");
s = beers != 1 ? "s" : "";
printf("%s bottle%s of beer on the wall.\n", howmany, s);
}
C++
C++ ist eine von der ISO genormte Programmiersprache. Sie wurde ab 1979 von Bjarne Stroustrup bei AT&T als Erweiterung der Programmiersprache C entwickelt. C++ ermöglicht sowohl die effiziente und maschinennahe Programmierung als auch eine Programmierung auf hohem Abstraktionsniveau.C++ unterstützt mehrere Programmierparadigmen:
/*
* 99 bottles of beer in C++
*/
#include <iostream>
using namespace std;
int main()
{
int bottles = 99;
while ( bottles > 0 )
{
cout << bottles << " bottle(s) of beer on the wall," << endl;
cout << bottles << " bottle(s) of beer." << endl;
cout << "Take one down, pass it around," << endl;
cout << --bottles << " bottle(s) of beer on the wall." << endl;
}
return 0;
}
C#
C# (lies englisch c sharp, englische Aussprache [ˌsiːˈʃɑːp]) ist eine vom Softwarehersteller Microsoft im Rahmen seiner .NET-Strategie entwickelte Programmiersprache. C# ist bei ECMA und ISO als Standard registriert.C# unterstützt mehrere Programmierparadigmen:
/*
* 99 bottles of beer in C#
*/
using System;
using System.Linq;
using System.Text;
namespace NinetyNineBottles
{
class Beer
{
static void Main(string[] args)
{
StringBuilder beerLyric = new StringBuilder();
string nl = System.Environment.NewLine;
var beers =
(from n in Enumerable.Range(0, 100)
select new {
Say = n == 0 ? "No more bottles" :
(n == 1 ? "1 bottle" : n.ToString() + " bottles"),
Next = n == 1 ? "no more bottles" :
(n == 0 ? "99 bottles" :
(n == 2 ? "1 bottle" : n.ToString() + " bottles")),
Action = n == 0 ? "Go to the store and buy some more" :
"Take one down and pass it around"
}).Reverse();
foreach (var beer in beers)
{
beerLyric.AppendFormat("{0} of beer on the wall, {1} of beer.{2}",
beer.Say, beer.Say.ToLower(), nl);
beerLyric.AppendFormat("{0}, {1} of beer on the wall.{2}",
beer.Action, beer.Next, nl);
beerLyric.AppendLine();
}
Console.WriteLine(beerLyric.ToString());
Console.ReadLine();
}
}
}
Labels: C, C#, C++, Java, Python
Montag, 18. November 2013
Musterlösung Römische Zahlen umwandeln (POS1: 2BHIF)
Mögliche Lösung zu Römische Zahlen umwandeln (POS1: 2BHIF).
Die Klasse könnte folgendermaßen programmiert werden. Das Dictionary enthält die möglichen "Ziffern" (unter Hochkomma, da bestimmte Ziffernkombinationen, wie zum Beispiel "IX", als eine Ziffer gelten). Zur Umrechnung müssen die Werte absteigend sortiert werden, damit die richtige "Ziffer" (z.B. "IX" für 9) verwendet wird.
Bei der Umrechnung in römische Zahlen wird der Reihe nach von der größten zur kleinsten "Ziffer" (daher absteigend sortiert) probiert, ob der Wert enthalten ist. Ist das der Fall, dann wird die "Ziffer" an den String angehängt und der entsprechende Wert von der Zahl abgezogen. Zum Beispiel 1999
1999 M 999 IM 0 ferigoder 392
392 C 292 C 192 C 92 XC 2 I 1 I 0 fertig
Bei der umgekehrten Umrechnung wird der Reihe nach probiert, ob am Beginn der römischen Zahl eine bestimmte "Ziffer" vorkommt. Ist dies der Fall, so wird der entsprechende Wert zum Ergebnis dazugezählt. Mit einem Zähler wird geprüft, dass keine Ziffer mehr als drei mal vorkommt. Zum Beispiel CCCXCII
CCCXCII 100 (C) CCXCII 200 (C) CXCII 300 (C) XCII 390 (XC) II 391 (I) I 392 (I)
Zum Testen wird einfach eine Liste von Zahlen verwendet, die in römische Zahlen und wieder zurück gerechnet werden. Ungültige Zahlen liefern eine Exception, die bei einem entsprechenden Testfall kommen muss:
# test value error
try:
ra = RomanNumber("VIIII")
assert(False)
except ValueError:
pass
Die gesamte Klasse könnte also so aussehen:
#!/usr/bin/env python3
"""
File: RomanNumber.py
Desc: class for roman numbers
Created: 2013-11-18, Harald R. Haberstroh
"""
class RomanNumber:
"""Roman numbers.
Internal representation is always the integer value.
This implementation stores both values (integer and roman).
"""
digits = { "I":1, "V":5, "X":10, "L":50, "C":100, "D":500, "M":1000,
"IV":4, "IX":9, "XL":40, "XC":90, "CD":400, "CM":900}
keys = list(digits.items())
keys.sort(key=lambda x: -x[1])
def __init__(self, value):
"""Initialize with value.
If type of value is int, than this is the integer value.
If type of value is str, than this is a roman number, which has
to be converted into the internal int-value"""
if type(value) is str:
self.roman = value
self.intval = self.__toInt(value)
else:
self.intval = value
self.roman = self.__toRoman(value)
def toRoman(self):
"""returns string with roman representation"""
return self.roman
def toInt(self):
"""returns integer value of roman number"""
return self.intval
def add(self, other):
"""add the value of other (RomanNumber) to own (self) value and
return a new RomanNumber object."""
return RomanNumber(self.intval + other.toInt())
def sub(self, other):
"""subtract the value of other (RomanNumber) from own (self) value and
return a new RomanNumber object."""
return RomanNumber(self.intval - other.toInt())
def mul(self, other):
"""multiply the value of other (RomanNumber) with own (self) value and
return a new RomanNumber object."""
return RomanNumber(self.intval * other.toInt())
def div(self, other):
"""divide (integer division) own value by the value of other value and
return a new RomanNumber object."""
return RomanNumber(self.intval // other.toInt())
def __str__(self):
"""returns the same value as toRoman(self)"""
return "%s (%d)" % (self.roman, self.intval)
def __toRoman(self, intval):
romval = ""
for digit, val in self.keys:
while intval >= val:
romval += digit
intval -= val
return romval
def __toInt(self, romval):
roman = romval.upper()
intval = 0
for digit, val in self.keys:
cntDigit = 0 # count same group
while roman.startswith(digit):
intval += val
roman = roman[len(digit):]
cntDigit += 1
if cntDigit >= 4:
raise ValueError()
return intval
if __name__ == '__main__':
zahlen = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 21, 32, 43, 48, 49, 54, 65, 76, 87, 98,
99, 100, 201, 302, 403, 491, 499, 504, 605, 706, 807, 908, 999, 1001,
1279, 1331, 1496, 1883, 1949, 1967, 1990, 1999, 2006, 2013]
for f in zahlen:
rn = RomanNumber(f)
# print('%4d: %20s - %4d' % (f, rn.toRoman(), rn.toInt()))
assert(f == rn.toInt())
for i in range(len(zahlen) // 2):
ra = RomanNumber(zahlen[i])
rb = RomanNumber(zahlen[-i])
rc = ra.add(rb)
print(ra, "+", rb, "=", rc)
assert(zahlen[i] + zahlen[-i] == rc.toInt())
rc = rb.sub(ra)
print(rb, "-", ra, "=", rc)
assert(zahlen[-i] - zahlen[i] == rc.toInt())
for i in range(len(zahlen) // 8):
ra = RomanNumber(zahlen[i])
rb = RomanNumber(zahlen[len(zahlen) // 2 - i])
rc = ra.mul(rb)
print(ra, "*", rb, "=", rc)
assert(zahlen[i] * zahlen[len(zahlen) // 2 - i] == rc.toInt())
# test value error
try:
ra = RomanNumber("VIIII")
assert(False)
except ValueError:
pass
print("all tests passed")
Beim romancalc.py wird jeder Schritt mit einem try - except - Block umgeben, um die Fehler- und Sonderfälle zu behandeln.
Eine Spezialität ist der Aufruf des entsprechenden Operators. Hier wird ein Dictionary mit den möglichen Operationen verwendet, wobei der Aufruf als Funktion und nicht als Methode stattfindet (der erste Parameter self enthält ja das Objekt, welches dann explizit mit übergeben wird).
Das gesamte Modul könnte wie folgt aussehen:
#!/usr/bin/env python3
"""
File: romancalc.py
Desc: simple caluculator for roman numbers, using RomanNumber
Created: 2013-11-18, Harald R. Haberstroh
"""
from RomanNumber import RomanNumber
import sys
operators = { "+":RomanNumber.add, "-":RomanNumber.sub,
"*":RomanNumber.mul, "/":RomanNumber.div }
while True:
try:
line = input(">>> ")
except EOFError:
break
try:
a, op, b = line.split()
except ValueError:
print("syntax error", file=sys.stderr)
continue
if a.isdigit():
a = int(a)
if b.isdigit():
b = int(b)
try:
ra = RomanNumber(a)
rb = RomanNumber(b)
except ValueError:
print("invalid roman number", file=sys.stderr)
continue
try:
rc = operators[op](ra, rb)
print(ra, op, rb, "=", rc)
except KeyError:
print("invalid operator '%s'" % (op), file=sys.stderr)
Labels: Aufgabe, Lösung, POS1-2, Python
Römische Zahlen umwandeln (POS1: 2BHIF)
Römische Zahlen
Schreiben Sie eine Klasse RomanNumber, welche es erlaubt, mit römischen Zahlen zu rechnen bzw. römische Zahlen in ganze Zahlen und umgekehrt umzurechnen. Schreiben Sie dazu Methoden zum Umrechnen von ganzen Zahlen (1 bis 3000) in Römische Zahlen und umgekehrt. Die römischen Ziffern haben folgende Bedeutung:
I ... 1 V ... 5 X ... 10 L ... 50 C ... 100 D ... 500 M ... 1000Beachten Sie, dass nur jeweils drei gleiche Ziffern hintereinander geschrieben werden. Stattdessen wird die nächst größere Einheit benutzt und eine Einheit abgezogen (XC = 90, XCIX = 99, IX = 9, VIII = 8).
class RomanNumber:
"""Roman numbers.
Internal representation is always the integer value.
"""
def __init__(self, value):
"""Initialize with value.
If type of value is int, than this is the integer value.
If type of value is str, than this is a roman number, which has
to be converted into the internal int-value"""
pass
def toRoman(self):
"""returns string with roman representation"""
pass
def toInt(self):
"""returns integer value of roman number"""
pass
def add(self, other):
"""add the value of other (RomanNumber) to own (self) value and
return a new RomanNumber object."""
pass
def sub(self, other):
"""subtract the value of other (RomanNumber) from own (self) value and
return a new RomanNumber object."""
pass
def mul(self, other):
"""multiply the value of other (RomanNumber) with own (self) value and
return a new RomanNumber object."""
pass
def __str__(self):
"""returns the value like 'XXII (23)'"""
pass
Ergänzen Sie dieses Gerüst zu einer funktionierenden Klasse und schreiben Sie ein Testprogramm mit fix programmierten Testfällen.
Schreiben Sie weiters ein zweites Modul, welches die Klasse RomanNumber importiert und jeweils eine Zeile der Art
zahl op zahleinliest, die Operation
op (+, - oder *) ausführt und das Ergebnis ganzzahlig und als Römische Zahl ausgibt. zahl ist jeweils eine ganze Zahl oder eine römische Zahl.
Beispielaufrufe:
~/work/tmp > python romancalc.py >>> 24 + 27 LI (51) >>> LI - 24 XXVII (27) >>> LI - XXIV XXVII (27) >>> ~/work/tmp >
Informationen finden Sie unter:
Labels: Aufgabe, POS1-2, Python, Testen
Mittwoch, 13. November 2013
Einführung Objektorientiertes Programmieren (POS1: 2BHIF)
Es folgt ein Beispiel:
Aufgabe: Finden Sie Klassen bzw. Objekte zu folgenden Begriffen: Leo, Tiger, Samurai, Elefant, Taigon, Benjamin Blümchen, Tier, Löwe
Lösung: Beim Programmieren muss man aus einer Aufgabenstellung immer wieder Objekte und Klassen identfizieren, die man zur Implementierung benötigt. Man kann z.B. alle Subjekte der Aufgabenstellung suchen und sich dazu fragen "ist das ein Objekt oder sind das viele Objekte?". In letzterem Fall hat man einen Kandidaten für eine Klasse. Sonst ist es ein Objekt. Nicht alle Objekte werden für das Programm benötigt.
Bei diesem Beispiel ist nur eine Liste von Tieren und Namen gegeben. Namen sind normalerweise Objekte, die verschiedenen Tiere sind natürlich Klassen.
Wir werden also die Klassen Tier, Tiger, Löwe und Elefant haben. Die anderen Begriffe sind konkrete Namen. Weiters können wir die "is-a" ("ist-ein") Beziehung Tiger is-a Tier, Löwe is-a Tier und Elefant is-a Tier ausmachen.
Damit ergibt sich folgendes Bild:

Kästchen mit unterstrichenen Namen stellen konkrete Objekte dar.
Die strichlierten Pfeile stellen die Instanzierung dar. Sie sind in Pfeilrichtung zu lesen: Leo ist-ein-konkreter Löwe (Leo is-instance-of Löwe) oder Samurai ist-ein-konkreter Tiger.
Die Pfeile mit Dreiecksspitzen und durchgehenden Linien stehen für die Vererbung (is-a, ist-ein), Beispielsweise Löwe ist-ein Tier (Löwe is-a Tier).
In Python könnte man das Beispiel so implementieren:
class Tier:
def __init__(self):
self.name = ""
def setName(self, name):
self.name = name
def __str__(self): # toString() in Java
return self.name
class Loewe(Tier):
pass
class Elefant(Tier):
pass
class Tiger(Tier):
pass
leo = Loewe()
leo.setName("Leo")
benjamin = Elefant()
benjamin.setName("Benjamin Blümchen")
samurai = Tiger()
samurai.setName("Samurai")
taigon = Tiger()
taigon.setName("Taigon");
print(leo)
print(benjamin)
print(samurai)
print(taigon)
Erstellen Sie für die folgenden Beispiele passende Klassen- bzw. Objektdiagramme (UML) und implementieren Sie die in Python!
Beispiel 1
Mensch, Lebewesen, Mohrle, Mann, Paul, Paula, Helmut, Rex, Frau, Tier, Susi, Biene Maya, Pinocchio
Beispiel 2
Verkehrsmittel, Schiff, Auto, Porsche von Herrn Mayer, Dreirad, Fahrrad, Dreirad von Maxi, Sportwagen, Käfer von Paula, Düsenjet von Daniel
Montag, 11. November 2013
Python class (POS1: 2BHIF)
Erzeugen Sie eine einfache Klasse für Sportler. Sportler haben in unserem Beispiel einen Namen, ein Geburtsdatum und eine Liste von Zeiten (z.B. wie schnell ist der die letzten 100m-Läufe gelaufen).
Nennen Sie die Klasse Sportler
class Sportler: pass
Definieren Sie eine Methode zur Ermittlung der besten (Lauf-)Zeit (minimale Zeit aus der Liste von Zeiten).
Legen Sie mindestens 3 Sportler an und lassen Sie deren Namen, das Geburtsdatum und Bestzeit ausgeben.
Labels: Aufgabe, POS1-2, Python
Montag, 4. November 2013
Python Objekte, Wiederholung Aufrufstack (POS1: 2BHIF)
Objekte
In Python sind alle Elemente Objekte. Folgendes Beispiel enthält ein paar solche Objekte:def fun(x): # auch ein Objekt!
y = x * x
return y
f2 = fun # f1 ist eine Refernz auf fun
lst = [1, 2, fun] # Liste mit 3 Objekten
l2 = lst # l2 ist eine Refernz auf obige Liste
erg = fun(2)
print(erg)
erg = f2(3)
print(erg)
print(f2 == fun)
print(l2 == lst)
print(lst)
Folgendes Bild zeigt den Speicher, wenn das Progarmm in der Zeile 3 angelangt ist, nach dem
f2(3) (ist ja fun(3)) in der Zeile 12 Aufgerufen wurde.
Sie können den Ablauf unter folgendem Link testen: objects.py
Sie sehen auf der rechten Seite die Objekte, welche Python angelegt hat. Der linke Bereich ("Frames") zeigt den Speicher, den Python für die (globalen) Variablen anlegt sowie den Speicher für die aufgerufene Funktion. Für jede Funktion wird so ein Bereich (Frame) angelegt und beim beenden wieder zerstört.
Pfeile stellen Referenzen dar. Zum Beispiel stellt der Pfeil von
lst zum Listenobjekt [1, 2, fun] dar. Auch l2 ist eine Referenz zu dieser Liste.
In dieser Liste gibt es eine weitere Referenz zur Funktion
fun. Funktionsnamen sind also Referenzen zu "Funktions-Objekten" (die den Code der Funktion "enthalten").
Aufrufstack
Beim folgenden Beispiel können Sie sehen, wie Frames sich bei den Aufrufen der Funktionfact() stapeln und dann in Folge wieder zerstört werden:
def fact(n):
if n > 1:
return n * fact(n - 1)
else:
return 1
f = fact(5)
print(f)
Folgendes Bild zeigt die Frames, wenn das Programm die Zeile 5 erreicht (aber nicht ausgeführt) hat. Sie sehen einen Stapel von Frames. Ein Frame pro Aufruf. Diese Frames werden anschließend bei jedem
return wieder zerstört. Man nennt diesen Stapel Aufrufstack:
Sie können den Ablauf unter folgendem Link testen: fact.py
Klassen
Bei Klassen handelt es sich um benutzerdefinierte Typen. D.h. es werden Typen angelegt, für die benutzerdefinierte Methoden (also objektgebundene Funktionen) definiert werden können:class Car:
def __init__(self, cartype, kind, serNr):
self.cartype = cartype
# die Attribute type,
self.kind = kind
# kind und
self.serNr = serNr
# serNr sind in der Instanz
def maxSpeed(self):
if self.kind == "pickup": # Wenn Pickup, dann langsamer
return 100.0
else:
return 130.0
passat1 = Car("VW/Passat", "regular_car", 11142)
jetta1 = Car("VW/Jetta", "small_car", 11143)
ram1 = Car("Dodge/Ram", "pickup", 22242)
fleet = [passat1, jetta1, ram1] # Fuhrpark
for car in fleet:
print(car.cartype, car.maxSpeed(), "km/h")
Mittels der Anweisung
class wird ein neuer Typ definiert. Dieser heißt in diesem Fall ‘Car’. Wir sehen, dass es sich bei der class Anweisung ebenfalls um eine Block - Anweisung handelt, da nach der Bezeichnung der Klasse (Car) der Doppelpunkt folgt und die danach folgenden Methoden eingerückt sind.
Die einzelnen Methoden werden wie Funktionen definiert. D.h. die Definition erfolgt durch das Schlüsselwort
def. Als Unterschied gibt wird jedoch ein zusätzlicher Parameter an erster Stelle angeführt, der zur Ausführungszeit der Methode mit der Referenz des aktuellen Objektes vom Laufzeitsystem belegt wird.
Das folgende Bild zeigt, wie Python den Speicher für die Objekte und die Klasse angelegt hat.
Sie können das Programm hier ausführen car.py.
Die Ausgabe wäre wie folgt:
VW/Passat 130.0 km/h VW/Jetta 130.0 km/h Dodge/Ram 100.0 km/h
Durch Aufrufen der Klasse (durch Angabe des Klassennamens) und Übergabe der Initialisierungsparameter wird eine neue Instanz angelegt. Die übergebenen Parameter werden verwendet, um die spezielle Methdode
__init__ nach dem Anlegen der Instanz aufzurufen. D.h. zuerst wird das neue Objekt angelegt und danach wird diese spezielle Methode aufgerufen. Dazu wird auch dieser Methode die Referenz auf das gerade angelegte Objekt mitgegeben (als Parameter self).
D.h. in der Methode
__init__ werden die Attribute cartype, kind und serNr für das gerade erzeugte Objekt angelegt. D.h. ab diesem Zeitpunkt besitzt das Objekt diese Attribute. Die Methode maxSpeed kann danach ebenfalls auf diese Attribute zugreifen.
Attribute gehören also zu einem Objekt und können in den Methoden abgefragt und verändert werden. Anders als in anderen Programmiersprachen ist es jedoch so, dass der Zugriff auf diese Attribute nicht nur ausschließlich in den Methoden erfolgen kann. Diese Attribute können prinzipiell auch von außerhalb gelesen und verändert werden, wie man in obigem Beispiel in der Zeile 21 (
print(...)) sehen kann.
Übungen (POS1: 2BHIF)
Theorie
- Was ist eine Variable?
- Welche Grunddatentypen kennen Sie?
- Was ist ein Liste?
- Geben Sie einen Algorithmus (ohne Programmdetails) an, um alle Elemente einer Liste zu ermitteln, die ein bestimmtes Kriterium (z.B. ist größer als ein bestimmter Wert) erfüllen.
- Geben Sie einen Algorithmus (ohne Programmdetails) an, um alle Elemente eine Liste von Listen zu ermitteln, die ein bestimmtes Kriterium erfüllen.
- Geben Sie einen Algorithmus (ohne Programmdetails) an, um das Maximum aller Werte einer Liste zu ermitteln.
- Geben Sie einen Algorithmus (ohne Programmdetails) an, um das Minimum aller Werte einer Liste zu ermitteln.
- Geben Sie einen Algorithmus (ohne Programmdetails) an, um das Maximum aller Werte einer Liste von Listen zu ermitteln.
- Geben Sie einen Algorithmus (ohne Programmdetails) an, um das Minimum aller Werte einer Liste von Listen zu ermitteln.
- Was ist eine Funktion? Geben Sie ein Beispiel in Python inklusive der Verwendung der Funktion.
- Wozu benötigt man Kommentare?
- Wozu benötigt man Programmierrichtlinien?
- Was ist ein Dictionary in Python?
- Was bedeutet der Begriff "Sequenz" in Python? Geben Sie einige Beispiele.
- Was muss grundsätzlich (ohne Programmdetails) gemacht werden, um von einer Datei zu lesen?
- Was muss grundsätzlich (ohne Programmdetails) gemacht werden, um in eine Datei zu schreiben?
- Geben Sie einen Algorithmus (ohne Programmdetails) an, um alle Zeilen einer Textdatei zu ermitteln, die ein bestimmtes Kriterium (z.B. enthält einen bestimmten String) erfüllen.
- Welche Arten von Programm(ier)fehlern kennen Sie? Wie findet man diese Fehler?
- Was ist der Aufrufstack? Erklären Sie den Verwendungszweck und die Funktionsweise.
In diesem Blog gibt es bereits eine Reihe von Aufgaben. Vergleichen Sie Ihre Lösungen mit jenen Ihrer MitschülerInnen.
Hier noch ein paar "Grundübungen":
- Erstellen Sie ein Pythonprogramm, welches das Maximum einer Sequenz ermittelt. Definieren Sie dazu eine fixe Testsequenz mit folgenden Werten
[-1, -23, -2, -32, -89, -100, -1, -99]. Finden Sie weitere Beispieltestdaten. - Erstellen Sie ein Pythonprogramm, welches das Minimum einer Sequenz ermittelt. Definieren Sie dazu eine fixe Testsequenz mit folgenden Werten
[1, 23, 2, 32, 89, 100, 1, 99]. Finden Sie weitere Beispieltestdaten. - Erstellen Sie ein Pythonprogramm, welches die Häufigkeit von Elementen einer Sequenz (Liste) ermittelt. Definieren Sie dazu eine Testsequenz mit folgenden Werten
[1, 2, -3, 4, 2, 1, 10, -3, 4, 2, 2, 10]bzw.["hallo", "du", "test", "du", "Maus", "test", "Test"]. Das Ergebnis soll eine Liste von unterschiedlichen Werten sein und wie oft sie vorkommen. - Folgende Ausgabe soll erzeugt werden:
1 3 5 7 9. Lösen Sie die Aufgabe- mithilfe einer
while-Schleife - mithilfe einer
for-Schleife und des Modulo-Operators - mithilfe einer
for-Schleife ohne den Modulo-Operator
- mithilfe einer
- Folgende Ausgabe soll erzeugt werden:
1 2 4 7 11 16 22 29 37. Lösen Sie die Aufgabe- mithilfe einer
while-Schleife - mithilfe einer
for-Schleife
- mithilfe einer
Labels: Aufgabe, POS1-2, Python
Montag, 21. Oktober 2013
Testen und erweitern von text_analyzer.py (POS1: 2BHIF)
Ziel dieser Aufgabe ist es, fremden Code zu testen, zu verstehen und zu erweitern. Dazu werden Sie
text_analyzer.py von zwei Mitschülern testen und um unten beschriebene Funktionalität erweitern. Schreiben Sie dazu ein Modul test_text_analyzer, welches die Funktionen vom Modul text_analyzer importiert und testet.
Protokollieren Sie die Testläufe und beschreiben Sie die eventuell gefundenen Fehler in einer Textdatei
errors.txt. Haben Sie Fehler entdeckt, so korrigieren Sie diese, sodass die Tests fehlerfrei laufen.
Sollten Ihre Tests Fehler enthalten, so korrigieren sie diese ebenfalls (solche Fehler werden Sie u.U. erst finden, wenn Sie das zweite Programm testen).
Ergänzen Sie die Funktionalität von
text_analyzer um die Funktion read_sentences(file), welche aus der geöffneten Datei file (d.h. die Datei muss vor dem Aufruf dieser Funktion geöffnet werden) Zeilen liest und in der selben Form wie die bereits bestehende Funktion input_sentences() liefert.
Ändern/Ergänzen Sie
text_analyzer um ein main, welches prüft, ob Dateinamen auf der Kommandozeile angegeben wurden, diese Dateien der Reihe nach öffnet und das (End-)Ergebnis der Funktionen analyze_words(lst) und sort_letters(dic) ausgibt. Weiters sollen auch die Häufigkeiten der Worte, absteigend sortiert nach Häufigkeit (genau wie sort_letters(dic)) ausgegeben werden (braucht man eine neue Funktion?). Dabei soll die Ausgabe formatiert sein (also nicht nur die Listen bzw. Dictionaries ausgeben).
Werden keine Dateinamen angegeben, so ist wieder von der Konsole zu lesen.
Die Option
-h gibt eine kurze Hilfe aus.
Die Einteilung der Gruppen finden Sie in der Schule unter
/home/teachers/hp/public/2bhif/2013_2bhif_aufgabe5_gruppeneinteilung.pdf.
Labels: Aufgabe, POS1-2, Python, Testen
Freitag, 11. Oktober 2013
Aufgabe newprog.py (POS1: 2BHIF)
Neue Programmdateien haben im Allgemeinen eine ziemlich fixe (Anfangs-)Struktur. So wird immer ein Programmkopf (Kommentar) benötigt, der den Namen des Autors und andere Informationen enthält. Für Python sieht das z.B. so aus:
""" author: Maier Maria matnr: d84123 file: newprog.py desc: Erstellen eines Programmgerüsts aus einer Vorlage. date: 2010-10-22 class: 5AHDVK catnr: 23 """
Schreiben Sie ein Pythonprogramm newprog.py, welches aus einer Vorgabedatei so ein Programmgerüst erzeugt. In dieser Vorgabedatei gibt es Wörter, die dann von newprog.py durch die entsprechenden Werte ersetzt werden. Obiges Gerüst ist aus folgender Vorgabedatei entstanden:
"""
author: AUTOR
matnr: EVIDENZNUMMER
file: DATEINAME
desc: ZWECK
date: DATUM
class: KLASSE
catnr: KATALOGNUMMER
"""
if __name__ == '__main__':
pass
Für die Ersetzungen soll ein Dictionary verwendet werden, z.B.:
ersetzungen = {
"DATEINAME": progname,
"ZWECK": zweck,
"DATUM": datum,
"AUTOR": "Maier Maria",
"KATALOGNUMMER": "23",
"EVIDENZNUMMER": "d84123",
"KLASSE": "5AHDVK"
}
progname, zweck, datum müssen natürlich vorher bestimmt werden (eingegeben).
Zur Bestimmung des Datums verwenden Sie strftime():
from time import strftime
datum = strftime("%F")
strftime() kennt verschiedenste Formatangaben und liefert die aktuelle Uhrzeit bzw. Datum formatiert zurück. Hilfe mit help(strftime) in Python bzw. man strftime von der Shell (liefert die Beschreibung der C-Funktion, aber die Formatangaben gelten auch für Python).
Die Vorgabedatei und der Name der zu erzeugenden Datei sind auf der Kommandozeile anzugeben, z.B.:
~/work/tmp > python newprog.py vorgabe.py meinNeuesProgramm.py ~/work/tmp >
Wird keine Vorgabedatei angegeben, so wird eine Standardvorgabedatei verwendet:
~/work/tmp > python newprog.py meinNeuesProgramm.py ~/work/tmp >
Falls meinNeuesProgramm.py schon existiert, dann darf diese Datei nicht überschrieben werden:
~/work/tmp > python newprog.py meinNeuesProgramm.py 'meinNeuesProgramm.py' already exists! ~/work/tmp >
Sie können dazu folgende Funktion verwenden (Aufrufbeispiel im Home-Verzeichnis):
>>> from os.path import exists
>>> exists(".bashrc")
True
>>> exists(".bashrc__")
False
>>>
Labels: Aufgabe, POS1-2, Python
Mittwoch, 9. Oktober 2013
Musterlösung zu Aufgabe 2 "Denksport mit Python, erste Anwendung von Mercurial" (POS1: 2BHIF)
#!/usr/bin/env python3
"""
File: pythagorean_triple.py
Desc: Ein Programm zur Bestimmung eines pythagoräischen Tripel (a2+b2=c2
für a < b < c), wobei a+b+c == 1000.
Created: 2013-09-23, Harald R. Haberstroh
"""
from sys import argv
from math import sqrt
if __name__ == '__main__':
summe = 1000
if len(argv) == 2:
summe = int(argv[1])
for a in range(1, summe // 3):
for b in range(a + 1, summe // 2):
a2 = a * a
b2 = b * b
c2 = a2 + b2
c = sqrt(c2)
if a < b < c and a + b + c == summe:
print(a, b, int(c))
print(int(a * b * c))
#!/usr/bin/env python3
"""
File: sumdigits2pow1000.py
Desc: calculate the sum of the digits of 2**1000 (exponent can be changed
with commandline argument)
Created: 2013-09-23, Harald R. Haberstroh
"""
from sys import argv
if __name__ == '__main__':
if len(argv) == 2:
exponent = int(argv[1])
else:
exponent = 1000
print(sum(list(map(int, list(str(2 ** exponent))))))
#!/usr/bin/env python3
"""
File: sumdigitsfact.py
Desc: calculate the sum of the digits of 100! (100 can be changed
with commandline argument)
Created: 2013-09-23, Harald R. Haberstroh
"""
from sys import argv
def fact(n):
"""n!"""
f = 1
for i in range(1, n + 1):
f *= i
return f
if __name__ == '__main__':
if len(argv) == 2:
n = int(argv[1])
else:
n = 100
print(sum(list(map(int, list(str(fact(n)))))))
Die Palindrom-Beispiele sind ganz ähnlich und wurden daher in ein Programm gepackt, bei dem man als Parameter auf der Kommandozeile die Anzahl der Stellen angeben kann (4, 6, 8). Zusätzlich kann noch '-l' angegeben werden, um eine Liste der Produkte zu erhalten. Die Ergebnisliste ist nicht ganz vollständig, denn es wird das Ergebnis des Produkts als Schlüssel verwendet. Damit gehen Lösungen wie zum Beispiel 111111 = 143 * 777 = 231 * 481 = 259 * 429 verloren.
#!/usr/bin/env python3
"""
File: palindrome.py
Desc: largest palindrome of product of two n/2-digit numbers with n digits
Created: 2013-09-23, Harald R. Haberstroh
"""
from sys import argv
def checkPalindrom(s):
"""
checks whether string is a palindrome
"""
l = len(s)
for i in range(l // 2):
if s[i] != s[l - i - 1]:
return False
return True
def genPalindrom(n):
"""
build palindrome out of products
"""
# Dictionary only for list of palindromes not for maximum
palindromes = {}
products = []
maxPalindrome = 0
maxPalindromeFactors = ""
for i in range(10**((n - 1) // 2), 10 ** (n // 2)):
for j in range(10**((n - 1) // 2), 10 ** (n // 2)):
product = str(i * j)
if checkPalindrom(product):
if not product in palindromes:
palindromes[product] = str(i) + " * " + str(j) + " = " + product
products.append(product)
if int(product) > maxPalindrome:
maxPalindrome = int(product)
maxPalindromeFactors = str(i) + " * " + str(j) + " = " + product
return maxPalindromeFactors, palindromes
if __name__ == '__main__':
n = 2
if len(argv) > 1:
n = int(argv[1])
maxPalindrome, palindromes = genPalindrom(n)
if "-l" in argv:
lstPalindromes = list(palindromes.values())
lstPalindromes.sort()
for palindrome in lstPalindromes:
print(palindrome)
print("largest palindrome: %s" % maxPalindrome)
Labels: Lösung, POS1-2, Python
Musterlösung zu Wiederholung Python (POS1: 2BHIF)
"""
text_analyzer.py
Task 1: Repeat previous material (1st class)
2012-09-10, Harald R. Haberstroh (hp@htlwrn.ac.at)
"""
def input_sentences():
'''returns al list of sentences/lines'''
lst = []
eof = False
while not eof:
try:
line = input("Satz: ")
lst.append(line)
except EOFError:
eof = True
return lst
def _remove_punctuation(string):
'''helper removes all punctuation marks within string'''
for punctuation in '''"',;.:-''':
string = string.replace(punctuation, " ")
return string
def split_sentences(lst):
'''split a list (lst) of sentences into list of list of words'''
wordlist = []
for sentence in lst:
wordlist.append(_remove_punctuation(sentence).split())
return wordlist
def purge_bad_words(lst):
'''remove all bad words (length less than 2 chars, words
containing non alphabetic chars)
'''
for sublist in lst:
idx = 0
while idx < len(sublist):
if not len(sublist[idx]) >= 2 or not sublist[idx].isalpha():
del(sublist[idx])
else:
idx += 1
return lst
def analyze_words(lst):
'''returns a dictionary of words (with the number of occurrences)
of the list of list of words'''
dict = {}
for sublist in lst:
for word in sublist:
word = word.lower()
if word in dict:
dict[word] += 1
else:
dict[word] = 1
return dict
def analyze_letters(lst):
'''returns a dictionary of letters (with the number of occurrences)
of the list of list of words'''
dict = {}
for sublist in lst:
for word in sublist:
for char in word.lower():
if char in dict:
dict[char] += 1
else:
dict[char] = 1
return dict
def purge_analyzed_letters(dic):
'''remove umlauts'''
for umlaut in "äöüß":
if umlaut in dic:
del(dic[umlaut])
return dic
def _key(tupl):
'''returns 2nd element of tuple for sorting'''
return tupl[1]
def sort_letters(dic):
'''returns a sorted list of tuples of letters, sorted by
number of letters'''
tuples = list(dic.items())
tuples.sort(key=_key, reverse=True)
return tuples
def test_input():
'''returns a fixed list of sentences for testing purposes'''
return ['Maxi und Mini verliefen sich im Wald, aber bald.',
'10 alte Fledermäuse flogen im Wald',
'Hat die alte Meisterhexe...',
"Seid's gewesen. Denn als Geister...",
'Erst hervor der alte Meister.']
if __name__ == '__main__':
#lst = input_sentences()
lst = test_input()
print('split_sentences(lst)')
wordlist = split_sentences(lst)
print(wordlist)
print('\npurge_bad_words(wordlist)')
wordlist = purge_bad_words(wordlist)
print(wordlist)
print('\nanalyze_words(wordlist)')
print(analyze_words(wordlist))
print('\nanalyze_letters(wordlist)')
dic = analyze_letters(wordlist)
print(dic)
print('\npurge_analyzed_letters(dic)')
dic = purge_analyzed_letters(dic)
print(dic)
print('\nsort_letters(dic)')
sorted_letters = sort_letters(dic)
print(sorted_letters)
print('\n\n*** task 9 ***\n')
print('''"abcdef".index("c")''') # ValueError: substring not found
print('''ValueError: substring not found''')
print('''"abcdef".index("g")''') # ValueError: substring not found
print('''ValueError: substring not found''')
print('''"abcdef".index("de")''')
print("abcdef".index("de"))
print('''"c" in "abcdef" ''')
print("c" in "abcdef")
print('''"g" in "abcdef" ''')
print("g" in "abcdef")
print('''"de" in "abcdef" ''')
print("de" in "abcdef")
print('''"abcdef"[2:4]''')
print("abcdef"[2:4])
print('''"abcdef"[2:]''')
print("abcdef"[2:])
print('''"abcdef"[-1]''')
print("abcdef"[-1])
print('''"abcdef"[2:-1]''')
print("abcdef"[2:-1])
print('''[1, 2, 3, 4, 5].index(3)''')
print([1, 2, 3, 4, 5].index(3))
print('''[1, 2, 3, 4, 5].index(9)''') # ValueError: 9 is not in list
print('''ValueError: 9 is not in list''')
print('''[1, 2, 3, 4, 5][5]''') # IndexError: list index out of range
print('''IndexError: list index out of range''')
print('''[1, 2, 3, 4, 5][2:4]''')
print([1, 2, 3, 4, 5][2:4])
print('''[1, 2, 3, 4, 5][-2]''')
print([1, 2, 3, 4, 5][-2])
print('''[1, 2, 3, 4, 5][5:9]''')
print([1, 2, 3, 4, 5][5:9])
print('''[1, 2, 3, 4, 5][4:]''')
print([1, 2, 3, 4, 5][4:])
print('''len("abc") + len(range(3)) + len({1, 2, 3}) + len({1: 2, 2: 3})''')
print(len("abc") + len(range(3)) + len({1, 2, 3}) + len({1: 2, 2: 3}))
Labels: Lösung, POS1-2, Python
Montag, 7. Oktober 2013
Aufgabe Python Kommandozeile, Textdateien lesen (POS1: 2BHIF)
Schreiben Sie folgendes Pythonprogramm:
cut.py, welches einen bestimmten Zeilenbereich der Eingabe (Text) ausgibt (und den Rest unterdrückt). Die Eingabe kann aus beliebig vielen Dateien, die als Kommandozeilenparameter angegeben werden, oder aus der Standardeingabe (Tastatur oder Eingabe umlenkung mit <) bestehen.
Für jede Datei soll dann der als Optionen angegebene Zeilenbereich ausgegeben werden.
Aufruf
cut.py [-f N] [-t N] [-h] [file]...Falls keine Optionen angegeben werden, dann sollen die ersten 10 Zeilen jeder Datei (oder Standardeingabe) ausgegeben werden.
Optionen
- -f N
- Der Zeilenbereich beginnt ab Zeile N. Entfällt diese Option, dann beginnt die Ausgabe bei der ersten Zeile.
- -t N
- Der Zeilenbereich endet bei Zeile N (inklusive). Entfällt diese Option, dann endet die Ausgabe bei der Zeile 10.
- -h
- Es soll eine kurze Hilfe mit ihrem Namen ausgegeben werden. Zum Beispiel:
cut.py [-f N] [-t N] [file]... -f N ... from line N (default 1) -t N ... to line N (default 10) Print given lines of each file. (c) 2012, Harald R. Haberstroh
Es soll keine weitere Ausgabe erfolgen!
Beispiel
Gegeben sei die Datei1.txt mit dem Inhalt (Zeilennummern nur zur Orientierung, nicht Inhalt der Datei):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, |
hh@knuth:~$ cut.py -h cut.py [-f N] [-t N] [file]... -f N ... from line N (default 1) -t N ... to line N (default 10) Print given lines of each file. (c) 2012, Harald R. Haberstroh hh@knuth:~$ cut.py 1.txt Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo hh@knuth:~$ cut.py -f 3 -t 12 1.txt vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. hh@knuth:~$ cut.py -t 3 1.txt Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren,
Beispiele für fehlerhafte Angaben
Eine ungültige Option wird angegeben:hh@knuth:~$ cut.py -x 23 1.txt
-t:
hh@knuth:~$ cut.py -f 23 -t 1.txt
hh@knuth:~$ cut.py -f 23 -t 12 1.txt
hh@knuth:~$ cut.py doesntexist.txt
Labels: Aufgabe, POS1-2, Python
Montag, 30. September 2013
Python Kommandozeilenparameter
Kommandozeile (unter Linux/Unix)
Gleich zur Kommandozeilenbearbeitung mit PythonViele Aufgaben lassen sich auch wesentlich schneller auf der Kommandozeile erledigen als mit der grafischen Oberfläche (Click-Click-Drag usw). Ein paar Beispiele (Shell bedeutet hier Kommandozeile):
Suche alle .c Dateien, die neuer sind als Makefile.
| Shell... | find . -name ' *.c' -newer Makefile -print |
| GUI... | Öffne den Explorer, navigiere zum entsprechenden Verzeichnis, Klicke auf die Datei Makefile und merke das Änderungsdatum bzw. Zeit.
Dann Starte Tools/Find und gib *.c als Suchkriterium ein. Wähle den Datumsreiter und gib das gemerkte Datum ein. Klicke OK. |
Erzeuge an zip/tar-Archiv meines Sourcecodes (C-Code).
| Shell... | zip archive.zip *.h *.c oder
tar cvf archive.tar *.h *.c |
| GUI... | Öffne ein ZIP-Werkzeug (z.B. WinZip), wähle "Neues Archiv", gib den Namen ein, wähle das (Quell-)Verzeichnis im Hinzufügen Dialog, setze den Filter auf *.c und klicke "Hinzufügen", dann setze einen weiteren Filter auf *.h und klicke "Hinzufügen" und schließe das Archiv wieder. |
Ein letztes Beispiel:
Welche Java-Dateien wurden letzte Woche geändert?
| Shell... | find . -name '*.java' -mtime +7 -print |
| GUI... | Klicke und navigiere zu "Suche Dateien", klicke auf "Name" und gib "*.java" ein, wähle "Datum letzte Änderung" und klicke auf "Beginndatum", gib das Startdatum des Projekts ein (wann war das, verd**** noch mal?). Weiters klicke auf "Endedatum" und gib das Datum von vor einer Woche ein (schau mal schnell auf einen Kalender...). Klicke "Suche". |
Befehls-Syntax
Unix (Linux) Befehle haben folgende einheitliche Struktur. Bis auf den Befehlsnamen (Programmname) sind grundsätzlich alle anderen Angaben optional.Befehlsname [Option...] [Argument...] [Ein-/Ausgabeumlenkung]Die eckigen Klammern deuten an, dass dieser Parameter optional ist. Die drei Punkte geben zusätzlich an, dass mehrere solcher Parameter möglich sind.
Optionen sind syntaktisch von anderen Argumenten unterscheidbar: sie beginnen mit einem Minus, haben einen Buchstaben und danach optional ein Argument für diese Option
-x [Argument]oder sie beginnen mit zwei Minus und einem Optionsnamen sowie dem optionalen Argument.
--Optionsname [Argument]
Befehlsargumente sind Dateinamen oder andere für den Befehl wichtige Informationen.
Normalerweise lesen Unix-Programme Eingaben vom Terminal und geben Ausgaben auf das Terminal aus. Diese Datenkanäle können durch Ein-Ausgabeumlenkung geändert werden. Diese Umleitungen unterscheiden sich ebenfalls von den Optionen und anderen Argumenten (< Eingabedatei, > Ausgabedatei und | für die Pipe).
- <
- Das Kommando liest von der angegebenen Datei (statt von der Tastatur).
- >
- Das Kommando schreibt in die angegebene Datei (statt auf das Terminal).
- |
- Die Ausgabe des Kommandos links vom | wird als Eingabe für das Kommando rechts vom | verwendet. Die Kommandos sind über eine Pipe (Leitung, Rohrleitung) verbunden.
hh@knuth:~$ cd workspace hh@knuth:~/workspace$ ls c2bf demo eclimd.log guidemo libbf programmierblog python python3 python-sum pythontest pythonX scm-demo _SCRIPTS_ unit-tests hh@knuth:~/workspace$ cd c2bf hh@knuth:~/workspace/c2bf$ ls 1tox cc GPL ld Makefile math README strip test.sh wrapper hh@knuth:~/workspace/c2bf$ cd cc hh@knuth:~/workspace/c2bf/cc$ ls ast.h c2bf-cc c2bf-dispast dispast.c dispast.o genbf genbf.h genbfmain.c genbfmain.o gram.o gram.y main.c main.o Makefile README.txt scan.l scan.o tests y.output y.tab.h hh@knuth:~/workspace/c2bf/cc$ ls *.c *.h ast.h dispast.c genbf.h genbfmain.c main.c y.tab.h hh@knuth:~/workspace/c2bf/cc$ ls -l *.c *.h -rw-rw-r-- 1 hh hh 21061 Aug 31 21:40 ast.h -rw-rw-r-- 1 hh hh 30503 Aug 31 21:40 dispast.c -rw-rw-r-- 1 hh hh 6627 Aug 31 21:40 genbf.h -rw-rw-r-- 1 hh hh 953 Aug 31 21:40 genbfmain.c -rw-rw-r-- 1 hh hh 917 Aug 31 21:40 main.c -rw-rw-r-- 1 hh hh 7631 Aug 31 21:45 y.tab.h hh@knuth:~/workspace/c2bf/cc$ cd hh@knuth:~$
Kommandozeilenparameter mit Python bearbeiten
Das (Standard-) Modulsys ermöglicht es von Python auf die Umgebung, in der Python läuft, zuzugreifen. In unserem Fall wenden wir uns der Kommandozeile zu.
#!/usr/bin/python3
import sys
print("commandline:")
for arg in sys.argv:
print(arg)
hh@knuth:/tmp$ vim cmd.py
hh@knuth:/tmp$ cat cmd.py
#!/usr/bin/python3
import sys
print("commandline:")
for arg in sys.argv:
print(arg)
hh@knuth:/tmp$ python3 cmd.py -o --option par1 par2
commandline:
cmd.py
-o
--option
par1
par2
hh@knuth:/tmp$ chmod +x cmd.py
hh@knuth:/tmp$ ./cmd.py -o --option par1 par2
commandline:
./cmd.py
-o
--option
par1
par2
hh@knuth:/tmp$
#!/usr/bin/python3dient dazu, dem Betriebssystem zu sagen, mit welchem Programm diese (Text-) Datei zu starten ist, wenn man sie mit
chmod +x file ausführbar gemacht hat.
Sie sehen, dass alle Parameter nach
python3 ausgegeben werden. Ist die Pythondatei ausführbar, bekommt man die (fast) dieselbe Ausgabe (./ vor einem Kommando bedeutet, dass dieses Kommando im aktuellen Verzeichnis und nicht im Pfad zu finden ist).
hh@knuth:/tmp$ python3 Python 3.2.3 (default, Sep 10 2012, 18:14:40) [GCC 4.6.3] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import sys >>> type(sys.argv) <class 'list'> >>>
sys.argv ist eine Liste, die alle Kommandozeilenparameter inklusive des Scriptnamens enthält. Das Pythonprogramm muss die Argumente entsprechend behandeln: Optionen erkennen, Argumente verwenden. Nur die Ein-/Ausgabeumlenkung braucht man nicht im Programm behandeln (solange man nur die Standardkanäle verwendet).
hh@knuth:/tmp$ ./cmd.py -o --option par1 par2 > outputfile hh@knuth:/tmp$ cat outputfile commandline: ./cmd.py -o --option par1 par2 hh@knuth:/tmp$
outfile "verschwindet" die Ausgabe in dieser Datei.
Ein einfaches Beispiel, das den "Typ" der Argumente ausgibt:
import sys
def info(progname):
"""print some information"""
print(str.format("""
usage:
{0} [-h] [parameter...]
prints type of parameters
Options:
-h ... this help
(c) 2012 Harald R. Haberstroh
""", progname))
if __name__ == '__main__':
if "-h" in sys.argv:
info(sys.argv[0])
else:
for arg in sys.argv:
if arg.isdigit():
print("number", arg)
elif arg.isalpha():
print("word", arg)
else:
print("string", arg)
hh@knuth:/tmp$ python3 cmdline.py 123 Harald '+$' -h
usage:
cmdline.py [-h] [parameter...]
prints type of parameters
Options:
-h ... this help
(c) 2012 Harald R. Haberstroh
hh@knuth:/tmp$ python3 cmdline.py 123 Harald '+$'
string cmdline.py
number 123
word Harald
string +$
hh@knuth:/tmp$
Nach der Ausgabe der Hilfe (Info) soll das Programm beendet werden. Damit kann man wie im obigen Beispiel einfach
-h an die Kommandozeile anhängen.
In der Hilfe/Info muss auch immer der Programmname wie im Beispiel ausgegeben werden (
sys.argv[0])!
Python Objekte, Aufrufstack (POS1: 2BHIF)
Objekte
In Python sind alle Elemente Objekte. Folgendes Beispiel enthält ein paar solche Objekte:def fun(x): # auch ein Objekt!
y = x * x
return y
f2 = fun # f1 ist eine Refernz auf fun
lst = [1, 2, fun] # Liste mit 3 Objekten
l2 = lst # l2 ist eine Refernz auf obige Liste
erg = fun(2)
print(erg)
erg = f2(3)
print(erg)
print(f2 == fun)
print(l2 == lst)
print(lst)
Folgendes Bild zeigt den Speicher, wenn das Progarmm in der Zeile 3 angelangt ist, nach dem
f2(3) (ist ja fun(3)) in der Zeile 12 Aufgerufen wurde.
Sie können den Ablauf unter folgendem Link testen: objects.py
Sie sehen auf der rechten Seite die Objekte, welche Python angelegt hat. Der linke Bereich ("Frames") zeigt den Speicher, den Python für die (globalen) Variablen anlegt sowie den Speicher für die aufgerufene Funktion. Für jede Funktion wird so ein Bereich (Frame) angelegt und beim beenden wieder zerstört.
Pfeile stellen Referenzen dar. Zum Beispiel stellt der Pfeil von
lst zum Listenobjekt [1, 2, fun] dar. Auch l2 ist eine Referenz zu dieser Liste.
In dieser Liste gibt es eine weitere Referenz zur Funktion
fun. Funktionsnamen sind also Referenzen zu "Funktions-Objekten" (die den Code der Funktion "enthalten").
Aufrufstack
Beim folgenden Beispiel können Sie sehen, wie Frames sich bei den Aufrufen der Funktionfact() stapeln und dann in Folge wieder zerstört werden:
def fact(n):
if n > 1:
return n * fact(n - 1)
else:
return 1
f = fact(5)
print(f)
Folgendes Bild zeigt die Frames, wenn das Programm die Zeile 5 erreicht (aber nicht ausgeführt) hat. Sie sehen einen Stapel von Frames. Ein Frame pro Aufruf. Diese Frames werden anschließend bei jedem
return wieder zerstört. Man nennt diesen Stapel Aufrufstack:
Sie können den Ablauf unter folgendem Link testen: fact.py
Labels: allgemeines, POS1-2, Python
Montag, 23. September 2013
Denksport mit Python, erste Anwendung von Mercurial (POS1: 2BHIF)
Lesen Sie Mercurial Einführung und legen Sie
- die Datei ~/.hgrc nach dem Muster des obigen Artikels an:
[ui] username = Vorname Name <i99999@student.htlwrn.ac.at>
- ein Projekt mit dem Namen brain_teasers an.
- ein Mercurial Repository an.
Schreiben Sie folgende Pythonprogramme:
- pythagorean_triple.py
- Es soll ein Pythagoreisches Tripel (a2 + b2 = c2 für a < b < c) für a + b + c == 1000.
- sumdigits2pow1000.py
- Es soll die Ziffernsumme (Quersumme, engl. cross sum) der Zahl 21000 ermittelt werden. Die Zahl soll als Programmargument angegeben werden.
- sumdigitsfact.py
- Es soll die Ziffernsumme der Fakultät von 100 (100!) ermittelt werden. Die Zahl soll als Programmargument angegeben werden.
- palindrome4.py
- Generiere 4-stellige Palindrome als Produkt 2-steliger Zahlen. Die Faktoren und das Palindrom soll ausgegeben werden. Da die Multiplikation kommutativ ist, müssen Duplikate entfernt werden: 74x66 == 66x74 (4884), also nur einmal ausgeben.
- palindrome6.py
- Generiere 6-stellige Palindrome als Produkt 3-steliger Zahlen. Gib das Maximum der Palindrome aus.
Labels: Aufgabe, mercurial, POS1-2, Python
Montag, 16. September 2013
Python - suchen und ersetzen einzelner Zeichen
Sie wollen in einem String zum Beispiel alle Dollar-Zeichen ($) durch Euro (€), alle Fragezeichen (?) durch Rufzeichen (!), einfache Hochkomma (') durch doppelte Hochkomma (") ersetzen und eckige Klammern ([ und ]) löschen.
Definieren Sie eine Übersetzungstabelle (Dictionary) und verwenden Sie die Methode str.translate(table)).
translation_table = {
"$": "€",
"?": "!",
"'": '"',
"[": None,
"]": None
}
teststring = """Das ist ein Test? Der kostet ['1000$']"""
print(teststring.translate(str.maketrans(translation_table)))
Folgendes wird dann ausgegeben:
hp@if211l $ python3
Python 3.2.3 (default, Apr 10 2013, 06:11:55)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> translation_table = {
... "$": "€",
... "?": "!",
... "'": '"',
... "[": None,
... "]": None
... }
>>>
>>> teststring = """Das ist ein Test? Der kostet ['1000$']"""
>>> print(teststring.translate(str.maketrans(translation_table)))
Das ist ein Test! Der kostet "1000€"
>>>
str.maketrans(table) erzeugt ein Dictionary mit den Unicode-Werten der Zeichen.
Tatsächlich können Sie einzelne Zeichen sogar durch ganze Strings ersetzen. Wenn Sie zB. Umlaute durch die entsprechenden HTML-Sequenzen ersetzen wollen, dann können Sie eine Tabelle wie folgt verwenden:
translation_table = {
"Ä": "Ä",
"ä": "ä",
"Ö": 'Ö',
"ö": "ö",
"Ü": "Ü",
"ü": "ü"
}
>>> translation_table = {
... "Ä": "Ä",
... "ä": "ä",
... "Ö": 'Ö',
... "ö": "ö",
... "Ü": "Ü",
... "ü": "ü"
... }
>>> "Übermäßig".translate(str.maketrans(translation_table))
'Übermäßig'
>>>
Labels: Python
Sonntag, 8. September 2013
Wiederholung Python (POS1: 2BHIF)
Die folgenden Aufgaben ermöglichen Ihnen einen Wiedereinstieg in das Programmieren mit Python. Das Rüstzeug zur Lösung sollten Sie in der ersten Klasse bekommen haben.
Googlen Sie nach 'python "reference card"' und suchen Sie eine passende Kurzreferenz.
- Schreiben Sie eine Funktion
input_sentencesin einem Modultext_analyzer, die den Benutzer nach beliebigen Sätzen fragt, diese in einer Liste abspeichert und danach zurückliefert. Das könnte also so aussehen:Bitte geben Sie die zu analysierenden Sätze ein (CTRL-D bricht ab): Satz: Maxi und Mini verliefen sich im Wald, aber bald. Satz: 10 alte Fledermäuse flogen im Wald Satz: Hat die alte Meisterhexe... Satz: Seid's gewesen. Denn als Geister... Satz: Erst hervor der alte Meister. Satz: <ctrl-d>
CTRL-D bewirkt ein Ende der Eingabe (EOF ... End Of File).
-
Fügen Sie dazu in diesem Modul einen Aufruf dieser Funktion ein, sodass das Modul sowohl als Modul als auch als Programm verwendet werden kann. Dies macht man üblicherweise folgendermaßen:
# prüft, ob das Modul als Programm aufgerufen wurde if __name__ == '__main__': # main lst = input_sentences()
-
Schreiben Sie eine Funktion
split_sentences(lst), die eine Liste solcher Sätze bekommt und eine Liste von Wortlisten zurückliefert, wobei die übergebene Listelstdirekt verändert werden soll.
Die Wortlisten entstehen indem man die Sätze an den Whitespace Zeichen und den Satzzeichen("',;.:-)trennt. Die Satzzeichen werden nicht benötigt.
Gehen Sie dazu folgendermaßen vor:- Ersetze zuerst alle Satzzeichen hintereinander durch Leerzeichen. Verwende dazu die
replaceMethode des Typsstr. - Trenne (splitte) danach den String in die einzelnen Wörter mittels der Methode
splitdes Typsstr.
>>> lst = ['Maxi und Mini verliefen sich im Wald, aber bald.', ... '10 alte Fledermäuse flogen im Wald', ... 'Hat die alte Meisterhexe...', ... "Seid's gewesen. Denn als Geister...", ... 'Erst hervor der alte Meister.'] >>> split_sentences(lst) [['Maxi', 'und', 'Mini', 'verliefen', 'sich', 'im', 'Wald',\ 'aber', 'bald'], ['10', 'alte', 'Fledermäuse', 'flogen', 'im', 'Wald'],\ ['Hat', 'die', 'alte', 'Meisterhexe'], ['Seid', 's', 'gewesen', 'Denn',\ 'als', 'Geister'], ['Erst', 'hervor', 'der', 'alte', 'Meister']] >>> lst [['Maxi', 'und', 'Mini', 'verliefen', 'sich', 'im', 'Wald',\ 'aber', 'bald'], ['10', 'alte', 'Fledermäuse', 'flogen', 'im', 'Wald'],\ ['Hat', 'die', 'alte', 'Meisterhexe'], ['Seid', 's', 'gewesen', 'Denn',\ 'als', 'Geister'], ['Erst', 'hervor', 'der', 'alte', 'Meister']]
Bei der obigen Ausgabe wurden zur besseren Lesbarkeit die Zeilen manuell umgebrochen und der Zeilenumbruch jeweils mit einem \ gekennzeichnet.
Baue diese Funktion in das Hauptprogramm ein.
- Ersetze zuerst alle Satzzeichen hintereinander durch Leerzeichen. Verwende dazu die
- Schreiben Sie eine Funktion
purge_bad_words(lst), die eine Liste von Listen von Wörtern erhält und alle diejenigen herauslöscht, die- weniger als 2 Zeichen lang sind oder
- nicht alphabetische Zeichen enthalten
>>> purge_bad_words(lst) [['Maxi', 'und', 'Mini', 'verliefen', 'sich', 'im', 'Wald', 'aber',\ 'bald'], ['alte', 'Fledermäuse', 'flogen', 'im', 'Wald'], ['Hat',\ 'die', 'alte', 'Meisterhexe'], ['Seid', 'gewesen', 'Denn', 'als',\ 'Geister'], ['Erst', 'hervor', 'der', 'alte', 'Meister']]
Wie leicht zu sehen sind sind die zu kurzen Wörter und die Wörter, die nicht-alphabetische Zeichen enthalten entfernt worden.
- Schreiben Sie eine Funktion
analyze_words(lst), die eine Liste wie aus dem vorhergehenden Punkt als Argument bekommt und ein Dictionary mit allen Worten als Keys und deren Häufigkeiten als Values zurückliefert, wobei aber alle Wörter nur klein geschrieben gezählt werden:>>> analyze_words(lst) {'wald': 2, 'mini': 1, 'aber': 1, 'gewesen': 1, 'flogen': 1, 'im': 2,\ 'hervor': 1, 'als': 1, 'verliefen': 1, 'maxi': 1, 'sich': 1,\ 'meister': 1, 'hat': 1, 'bald': 1, 'meisterhexe': 1, 'erst': 1,\ 'fledermäuse': 1, 'geister': 1, 'die': 1, 'alte': 3, 'und': 1,\ 'denn': 1, 'seid': 1, 'der': 1}
- Schreiben Sie eine Funktion
analyze_letters(lst), die wiederum eine Liste der Liste der Wörter bekommt und ein Dictionary mit Buchstaben als Keys und deren Häufigkeiten als Values zurückliefert. Wiederum werden alle Buchstaben als Kleinbuchstaben betrachtet:>>> analyze_letters(lst) {'a': 10, 'c': 1, 'b': 2, 'e': 28, 'd': 9, 'g': 3, 'f': 3, 'i': 12,\ 'h': 4, 'm': 7, 'l': 10, 'o': 2, 'n': 7, 's': 9, 'r': 10, 'u': 2,\ 't': 8, 'w': 3, 'v': 2, 'x': 2, 'ä': 1}
- Schreiben Sie nun eine Funktion
purge_analyzed_letters(dic), die alle Umlaute (ä, ü, ö) aus dem Dictionary (des vorhergehenden Punktes) entfernt:>>> purge_analyzed_letters(dic) {'a': 10, 'c': 1, 'b': 2, 'e': 28, 'd': 9, 'g': 3, 'f': 3, 'i': 12,\ 'h': 4, 'm': 7, 'l': 10, 'o': 2, 'n': 7, 's': 9, 'r': 10, 'u': 2,\ 't': 8, 'w': 3, 'v': 2, 'x': 2}
- Entwicklen Sie eine Funktion
sort_letters(dic), die ein Dictionary wie aus dem vorhergehenden Punkt bekommt und eine absteigend sortierte Liste von Tupel mit Buchstabe und Häufigkeit zurückliefert:>>> sort_letters(dic) [('e', 28), ('i', 12), ('a', 10), ('l', 10), ('r', 10), ('d', 9),\ ('s', 9), ('t', 8), ('m', 7), ('n', 7), ('h', 4), ('g', 3), ('f', 3),\ ('w', 3), ('b', 2), ('o', 2), ('u', 2), ('v', 2), ('x', 2), ('c', 1)]
- Probieren Sie aus:
"abcdef".index("c")"abcdef".index("g")"abcdef".index("de")"c" in "abcdef""g" in "abcdef""de" in "abcdef""abcdef"[2:4]"abcdef"[2:]"abcdef"[-1]"abcdef"[2:-1][1, 2, 3, 4, 5].index(3)[1, 2, 3, 4, 5].index(9)[1, 2, 3, 4, 5][5][1, 2, 3, 4, 5][2:4][1, 2, 3, 4, 5][-2][1, 2, 3, 4, 5][5:9][1, 2, 3, 4, 5][4:]len("abc") + len(range(3)) + len({1, 2, 3}) + len({1: 2, 2: 3})
Speichern Sie die Aufrufe und das Ergebnis in einer Dateilog.txt, welche Sie dann mit abgeben.
- Bauen Sie in ihr Main Testaufrufe aller Funktionen mit einer fixen Liste auf (Kommentieren Sie den Aufruf von
input_sentences()aus). Es soll jedes Stadium der Verarbeitung der Liste ausgegeben werden. Bauen Sie die Aufrufe aus obigem Punkt (Probieren Sie aus) ein und geben Sie das Ergebnis aus. Man muss den Programmcode (print()verwenden) sehen und das Ergebnis.
- Geben Sie das Beispiel ab, indem Sie
text_analyzer.pyundlog.txtin ein Archiv mit dem Namen Abgabename: 2013_2bhif_aufgabe1_Name_Vorname.tgz (Name ist Ihr Familienname und Vorname ist Ihr Vorname, wobei Sie Umlaute und scharfes s durch ASCII-Zeichen ersetzen müssen, also z.B.2013_2bhif_aufgabe1_grossauer_guenter.tgzfür Günter Großauer) packen und diese Datei auf demedvossh.htlwrn.ac.atnach/home/teachers/hp/abgabe/2bhif/kopieren.
Beachten Sie, dass Sie das oben angegebene Verzeichnis nicht lesen können, Sie können in dieses Verzeichnis wohl aber schreiben.
Denken Sie an den Header, der etwa so aussehen muss:""" author: Großauer, Günter matnr: i09666 file: bubblesort.py desc: sort lists with bubblesort date: 2013-09-08 class: 2bhif catnr: 33 """
Labels: Aufgabe, POS1-2, Python
Donnerstag, 4. Juli 2013
XML Datei aus einer ZIP-Datei mit Python ändern und wieder zurückschreiben (Hack für Probleme mit K3B und diversen MP3-Playern)
Mit k3b erzeuge ich ein neues Projekt, in dem ich die Songs in der Reihenfolge, die ich haben will hinzufüge. Dann speichere ich das Projekt und lasse die Dateinamen durch das Script in der Projektdatei ändern. Dann lade ich das Projekt und brenne die CD. Die Lieder sind dann in der richtigen Reihenfolge, weil die Namen mit einer Nummer wie hier 001 - Lied.mp3 versehen werden.
#!/usr/bin/env python
"""
change entries so that they are sorted by name used with k3b-data CDs (mp3
CDs).
Procedure:
1. make k3p project and add files.
2. save this project
3. close the project (leave k3b open)
4. run this script: numbermymp3.py your_project_name.k3p
4. load the project again.
5. as you can see, the files ar starting with 3-digit numbers preserving
the original order when adding the files.
2013-07-04, Harald R. Haberstroh
"""
import sys
import codecs
import zipfile
from xml.dom import minidom
def getfiles(zipfilename):
"""get dictionary filename:data with all files in zipfile"""
zf = zipfile.ZipFile(zipfilename)
files = {}
for info in zf.infolist():
files[info.filename] = zf.read(info.filename)
return files
def process(xmlstr):
"""process xml with file entries and change 'name' attribute according
to number of file (starting with 001)."""
xmldoc = minidom.parseString(xmlstr)
names = xmldoc.getElementsByTagName('file')
num = 1
for name in names:
numstr = "%03d" % num
name.attributes['name'].value = numstr + ' - ' + \
name.attributes['name'].value
num += 1
return xmldoc.toprettyxml().encode('utf-8')
def genzipfile(zipfilename, files):
"""generate new zipfile (k3b-file) with dict 'files' which has file name as
key and the content as data"""
zf = zipfile.ZipFile(zipfilename, mode='w')
try:
for name in files:
zf.writestr(name, files[name])
finally:
zf.close()
def main():
"""all to gether now"""
if len(sys.argv) != 2:
print "usage: " + sys.argv[0] + " k3b_project_name.k3b"
print "renames files so that the order is the same as in the project"
sys.exit(1)
fname = sys.argv[1]
files = getfiles(fname)
text = process(files['maindata.xml'])
files['maindata.xml'] = text
genzipfile(fname, files)
if __name__ == '__main__':
main()
Abonnieren Posts [Atom]


