Seite 1 von 1

Exceptions und Simulation

Verfasst: Mittwoch 14. Januar 2009, 17:07
von Madpuella
Hallo.
Ich versuche mich seit Stunden an einer Aufgabe zu dem Thema Exceptions und an einer Aufgabe zu Simulation. Irgendwie habe ich das alles noch nicht so richtig verstanden, und wollte durch Ausprobieren zu einer Lösung gelangen, aber das ist mir leider nicht gelungen.Undzwar geht es um folgendes Programm:

Buchstabenauswahl für Stadt-Land-Fluss

Code: Alles auswählen

def stadtlandfluss():
      print "Control-C für nächsten Buchstaben"
      while True:
           try:
                for i in range(97,122):
                     continue
except KeyboardInterrupt:
       e=raw_input(chr(i)+"  ('n' für 'nein')?       ")
       if e!="n":
           break
>>>
Control-C für nächsten Buchstaben
x ('n' für 'nein')? n
d ('n' für 'nein')?


Dieses Programm soll jetzt so geändert werden, dass Buch darüber geführt wird,dass kein Buchstabe zweimal angeboten wird, wobei das Programm folgende zwei Eingaben erhalten werden sollen:
1.für das Starten der Wahl eines neuen Buchstabens (oder Beenden des Programms)
2. wie oben den Abbruch durch Control-C

Es liegt folgendes Beispielverhalten vor:
>>>

Start: <RETURN> (Beenden:e)
Control-C für nächsten Buchstaben
Gewählter Buchstabe: u
Start: <RETURN> (Beenden:e)
Control-C für nächsten Buchstaben
Gewählter Buchstabe: y
Start: <RETURN> (Beenden:e)
Control-C für nächsten Buchstaben
Gewählter Buchstabe: r
Start: <RETURN> (Beenden:e)
Control-C für nächsten Buchstaben
Gewählter Buchstabe: q
Start: <RETURN> (Beenden:e) e
>>>

Da ich leider keine Ahnung habe, wie und wo ich in dem Programm etwas ändern muss, um die Aufgabe zu lösen, bin ich leider völlig überfordert und hoffe hier auf Hilfe....

Edit (BlackJack): Nach "Allgemeine Fragen" verschoben und Quelltext in Code-Tags gesetzt.

Verfasst: Mittwoch 14. Januar 2009, 17:17
von Madpuella
Leider ist die oben geschriebene Aufgabe nicht die einzige, die mir Probleme bereitet. Ich kämpfe schons eit einiger Zeit mit einer Aufgabe zum Thema Simulation. Undzwar lautet diese wie folgt:

Simulieren Sie das Verhalten einer Lampe mit drei Helligkeitsstufen, die durch Drücken des Lampenschalters durchlaufen werden:



>>> l=Lampe()
>>> print l
die Lampe ist aus
>>> l.schalter.druecken()
>>> print l
die Lampe leuchtet schwach
>>> l.schalter.druecken()
>>> print l
die Lampe leuchet hell
>>> l.schalter.druecken()
>>> print l
die Lampe leuchtet sehr hell
>>> l.schalter.druecken()
>>> print l
die Lampe ist aus
>>> l.schalter.druecken()
>>> print l
die Lampe leuchtet schwach
>>>


Ich habe leider absolut keine Ahnung, wie ich zu diesem Ergebnis gelangen soll. Denn vermutlich muss man hier mit class und dann mit def__init__ oder def__str__ arbeiten, aber ich krieg einfach nicht raus, was für Bedingungen ich formulieren muss, damit immer etwas anderes erscheint, wenn man nur print l eingibt (also so wie oben in der Aufgabenstellung bzw. Lösung). Das ist einfach viel zu hoch für mich, und ohne Hilfe komme ich leider absolut nicht weiter. Ich habe noch nichtmal rausfinden können, was ich alles klassifizieren und definieren muss ausser vielleicht
class Lampe:
def__str__(self):
return "die Lampe"

(falls das überhaupt richtig ist). Ich bin echt unfähig, um selbstständig die Aufgabe lösen zu können :-( Deshalb hoffe ich hier auf irgendeine Hilfe...
Lieben Gruß

Verfasst: Mittwoch 14. Januar 2009, 17:22
von helduel
Moin,

hast du schon mal ein Python-Tutorial durchgearbeitet? Das dürfte viele Fragen beantworten.

Gruß,
Manuel

Verfasst: Mittwoch 14. Januar 2009, 17:27
von derdon
Dieses Unterforum ist für "Links und Turorials" und nicht für "Allgemeine Fragen" gedacht. Setze deinen Code bitte in Code-Tags und achte auf die Einrückung. Warum geht die For-Schleife bei dir nur bis 122? Guck dir doch einfach noch mal die Beispiele von range() an, dann weißt du, warum du als Stop-Parameter 123 angeben möchtest.

Verfasst: Mittwoch 14. Januar 2009, 17:58
von BlackJack
@Madpuella: Du solltest mal das Tutorial aus der Python-Dokumentation durcharbeiten und vielleicht noch ein weiteres Tutorial oder Buch, welches Python-Grundlagen bis einschliesslich objektorientierte Programmierung vermittelt. Dabei aber bitte einen groooossen Bogen um das OpenBook von Galileo machen.

Irgendwie klingen die Problembeschreibungen auch nach Hausaufgaben!?

Und die Beispielsitzung zur Lampe ist IMHO ein wenig zu kompliziert. Ein "Schalter"-Objekt würde ich mir sparen und gleich auf dem Lampen-Exemplar eine Methode zum weiterschalten bereit stellen.

Verfasst: Montag 19. Januar 2009, 00:30
von lucia
Oh, ich glaube, wir sind im selben Kurs :D

Nein, ich suche keine Komplettlösung,
also ich habe mir da mal was zusammengeschrieben und zwar:

Code: Alles auswählen

>>> class Schalter():
	def __init__(self, Lampe):
		self.lampe=Lampe
	def druecken(self):
		self.lampe.current=(self.lampe.current +1) %3

		
>>> class Lampe():
	def __init__(self):
		self.schalter= Schalter(self)
		self.states= ["die Lampe ist aus",
			      "die Lampe leuchtet schwach",
			      "die Lampe leuchtet hell",
			      "die Lampe leuchtet sehr hell"]
		self.current = 0
	def __str__(self):
		return self.states[self.current]


Wenn ich es dann abrufe:

Code: Alles auswählen

>>> l=Lampe()
>>> print l
die Lampe ist aus
>>> l.schalter.druecken()
>>> print l
die Lampe leuchtet schwach
>>> l.schalter.druecken()
>>> print l
die Lampe leuchtet hell
>>> l.schalter.druecken()
>>> print l
die Lampe ist aus
>>> 
Anstatt in der letzten Zeile 'Die Lampe ist aus' zu drucken,
soll es ja eigentlich 'Die Lampe leuchtet sehr hell' zurückgeben.
Kann mir jemand sagen, was ich falsch gemacht habe?

Verfasst: Montag 19. Januar 2009, 02:33
von madfrog
Der Modulo Operator ... Es muß so lauten:

Code: Alles auswählen

self.lampe.current = (self.lampe.current + 1) % 4

Verfasst: Dienstag 20. Januar 2009, 08:28
von BlackJack
Noch besser wäre es wenn man statt der hart kodierten 4 die aktuelle Länge der Zustandsliste nimmt, dann funktioniert das Ganze auch noch, wenn man Zustände hinzufügt oder entfernt.

Und diese Berechnung gehört IMHO nicht in den Schalter sondern in die Lampe. So hat der Schalter zuviel wissen über die Implementierung der Lampe. Wenn man zum Beispiel von einer Liste mit Zuständen zu einer verketteten Liste wechselt, muss man plötzlich die Logik des Schalters verändern.

Code: Alles auswählen

from itertools import cycle


class Button(object):
    def __init__(self, callback):
        self.push = callback


class Lamp(object):
    STATES = ['is off', 'glows dim', 'glows bright']
    
    def __init__(self):
        self.states = cycle(self.STATES)
        self.state = self.states.next()
        self.button = Button(self._next_state)
    
    def __str__(self):
        return 'Lamp %s.' % self.state
    
    def _next_state(self):
        self.state = self.states.next()


def main():
    lamp = Lamp()
    for dummy in xrange(4):
        print lamp
        lamp.button.push()

Verfasst: Dienstag 20. Januar 2009, 12:25
von lucia
@madfrog: Danke, das war's. Manchmal hab' ich aber auch echt ein Brett vor dem Kopf.

@BlackJack: Wow, danke, das ist viel praktischer als meine Variante.

Zu der Stadt Land Fluss- Aufgabe.
Ja, das ist eine Hausaufgabe, die mittlerweile aber schon den Zenit überschritten hat, dennoch lässt sie mich nicht los. Hauptsächlich deshalb weil meine Code nicht so funktioniert, wie er soll.
Aussehen tut er so:

Code: Alles auswählen

>>> from string import ascii_lowercase
>>> letters=ascii_lowercase
>>> import random
>>> alreadyused=[]
>>> def chooseletter():
	return random.choice(letters)

>>> def checkletter(i):
	for i in alreadyused:
		if i ==x:
			return True
		else:
			return False

		
>>> def stadtlandfluss():
	while True:
		print "Start: <RETURN> (Beenden:e)"
		n=raw_input()
		if n!="e":
			break
		print "Control-C für nächsten Buchstaben"
		alreadyused=[]
		while True:
			try:
				i=chooseletter()
				for i in range(97,123):
					continue
			except KeyboardInterrupt:
				while checkletter(i):
					i=chooseletter()
					alreadyused.append(i)
				e=raw_input(chr(i)+" ('n' für 'nein')? ")
				if e!="n":
					break

Beispielverhalten:

Code: Alles auswählen

>>> stadtlandfluss()
Start: <RETURN> (Beenden:e)
e
Control-C für nächsten Buchstaben
i ('n' für 'nein')? n
k ('n' für 'nein')? n
z ('n' für 'nein')? n
z ('n' für 'nein')?
Start: <RETURN> (Beenden:e)
Es bietet Buchstaben doppelt an, was er ja aber nicht soll.
Und das Programm startet, wenn man 'e' eingibt, genau dann soll es ja aber eigentlich aufhören, mit Return soll es starten.
Bin für jeden Tipp dankbar.

Verfasst: Dienstag 20. Januar 2009, 12:51
von bwbg
Zunächst mal destruktive Kritik: Der Code ist gruselig. Das mag an der direkten Eingabe im Interpreter liegen und vor allem (oder dadurch) an den unnötigen globalen Bezeichnern - vor allem allreadyused ist so ein Kandidat.

Die Funktionen chooseletter (siehe unten) und checkletter (siehe auch Frage 1) sind m.E. unnötig. Es handelt sich um Einzeiler, welche jeweils nur einmal aufgerufen werden.

Meine Fragen:

1. Wozu dient der Bezeichner x?
2. Wozu dient der Bezeichner i?
3. Wozu dient der Bezeichner n?

Diese Fragen haben tatsächlich Sinn :wink:

---

Nun zu der Buchstabenwahl:

Mein erster Gedanke war, eine Liste mit den Buchstaben (a-z) zu generieren und diese "durchzumischen". Nun kann ein Buchstabe aus dieser Liste "gezogen" werden.

Exemplarisch:

Code: Alles auswählen

import string
import random

letters = list(string.ascii_lowercase)
random.shuffle(letters)

letter = letters.pop()
    # Wirft eine Exception (IndexError), wenn die Liste leer ist.
    # Die Anzahl der (verbleibenden) Elemente kann mit len()
    # abgefragt werden.
Grüße... Heiko

[

Verfasst: Dienstag 20. Januar 2009, 17:51
von lucia
Nachdem mir dann doch auch mal aufgefallen, dass beispielsweise chooseletter() doppelt gemoppelt ist etc. etc., hier die Überarbeitung und sie funktioniert sogar
:shock: :D

Code: Alles auswählen

def stadtlandfluss():
    chars=[]
    while not raw_input("Start: <RETURN> (Beenden:e) "):
        print "Control-C für nächsten Buchstaben"
        while True:
            try:
                for i in range(97,123):
                    continue
            except KeyboardInterrupt:
                if chr(i) not in chars:
                    chars.append(chr(i))
                    print "Gewählter Buchstabe: ", chr(i)
                    break
                else:
                    while chr(i) in chars and y < 123:
                        i+=1
                    chars.append(chr(i))
                    print "Gewählter Buchstabe: ", chr(i)
                    break
@bwbg: besser?

Verfasst: Dienstag 20. Januar 2009, 21:36
von BlackJack
@lucia: Noch was zum ersten Code:

Code: Alles auswählen

from string import ascii_lowercase as letters
Spart eine Zuweisung.

Zu `checkletter` fällt mir die Frage "Was ist `x`?" ein. Und etwas nach dem Muster

Code: Alles auswählen

if bedingung:
    return True
else:
    return False
kann man als ``return bedingung`` schreiben, denn das was bei Dir in der Bedingung steht *ist* ja schon ein Wahrheitswert.

Zum neuen Code: Du solltest da nicht mit Zahlen für Buchstaben arbeiten. Das ist unverständlich und spätestens wenn die Buchstaben nicht mehr nur aus dem ASCII-Bereich kommen und als Zahlen einen zusammenhängenden Bereich darstellen, funktioniert das so nicht mehr.

Verfasst: Mittwoch 21. Januar 2009, 09:06
von bwbg
BlackJack hat geschrieben:@lucia: Noch was zum ersten Code:

Code: Alles auswählen

from string import ascii_lowercase as letters
Spart eine Zuweisung.

...
Um eine Zuweisung kommt man schlussendlich nicht umher, wenn man meinen Ansatz verwenden möchte. letters wäre in diesem Falle ein Imutable (unveränderliches Objekt -> Zeichenketten und Tupel). random.shuffle und list.pop können bekannterweise nur auf mutables (veränderliches Objekt) angewendet werden.

Würde letters für sich mittels in verwendet werden, so sparte man sich schlussendlich die Zuweisung.

@BlackJack: "Was ist ein 'x'?" - eben solche Gedanken wollte ich erzwingen - nur eben weniger bei Dir :wink:

EDIT:
Es ist gerade Mittagspause, daher konnte ich kurz was zusammenschrauben. Anhand der Code-Schnippsel oben, konnte ich nicht wirklich auf das Endergebnis zielen (oder vielleicht habe ich einfach keine Zeit dazu)...

Vielleicht hilft es dem Verständnis trotzdem weiter.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import string
import random

def ask(letter):
    """ Fragt ab, ob ein Buchstabe (letter) gewählt werden soll. Gibt True
    zurück, wenn die Frage positiv beantwortet wurde, andernfalls False. """
    answer = raw_input('Buchstabe %s (j/n) :' % (letter,))
    if answer == 'j':
        return True
    return False

def main():
    letters = list(string.ascii_lowercase)
    random.shuffle(letters)
        # Liste mit allen Buchstaben des Alphabets in zufälliger Reihenfolge
    choosen_letters = []
        # Eine Liste mit Buchstaben, welche *positiv* gewählt wurden.

    # Ctrl-C wird in der Regel dazu verwendet (und auch das Verhalten wird
    #   vom Benutzer erwartet), dass Programm vorzeitig abzubrechen.
    #   Sollte es von der Aufgabenstellung her gewünscht gewesen sein, 
    #   es nur einer Ausnahme wegen zu verwenden, dann schlage ich folgendes
    #   Konstrukt vor:
    
    try:
        while True:
            if len(letters) <= 0:
                break
            letter = letters.pop()
            letter_choosed = ask(letter)
            if letter_choosed:
                choosen_letters.append(letter)
        
        print u'Sie haben folgende Buchstaben gewählt:'
        print choosen_letters

    except KeyboardInterrupt:
        print u'Sie haben die Abfrage vorzeitig abgebrochen...'
        print u'Bis dorthin haben Sie folgende Buchstaben gewählt:'
        print choosen_letters
      
        
if __name__ == '__main__':
    main()
Grüße... Heiko