Return 'Wert' = None

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Reboot21
User
Beiträge: 6
Registriert: Donnerstag 2. Juni 2016, 21:42

Hallo alle miteinander,

und zwar habe ich bei meinem kleinen Projekt das Problem, dass mir die Funktion 'unit()' nicht die Einheit ausgibt, sondern anstelle dessen 'None' ausgibt.
Nach längeren rumprobieren weiß ich nicht wie ich das Problem beheben kann.

Übrigens bin ich gegenüber jeglicher Kritik, Verbesserungsvorschlägen und Anregungen offen.

Mfg

Reboot21

Code: Alles auswählen

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



import sys, os, math						


global ERRORMSG_ONELEFT, ERRORMSG_ONELEFT2

UNITS = ["mm", "cm", "dm", "m", "km", "ha"]
ERRORMSG_ONELEFT = "Es sollte nur ein Wert fehlen!"
ERRORMSG_ONELEFT2 = "Es kann nur ein fehlender Wert errechnet werden!"




	#####################################################################
	##                     Allgemeine - Funktionen                     ##
	#####################################################################




def unit(n):
		
		for i in range(0, len(UNITS)): # Von 0 bis zur Länge der Einheit-Liste ('Items') 
		if eingabe == UNITS[i]: # Falls 'eingabe' = das i'te Objekt in UNITS
			if n == 1: # Falls potenz = 1
				return UNITS[i]
			elif n == 2: # Falls potenz = 2
				return UNITS[i] + "²"
			elif n == 3: # Falls potenz = 3
				return UNITS[i] + "³"


def cls():
    os.system('cls' if os.name=='nt' else 'clear')


def newLine(n):
	for n in range(1, n+1):
		print("")




	###############################################################
	##                     Menü - Funktionen                     ##
	###############################################################




def menu(): # Hauptmenü
	while 1:	
		print("Verfügbare Programme:\n\n"
			"[1] Dreiecksberechnung\n"
			"[2] Viereckberechnung\n"
			"[3] Vieleckberechnung\n"
			"[4] Kreisberechnung\n"
			"[5] Körperberechnung\n\n"
			"'q' eingeben, um das Programm zu beenden.\n")
	   
		eingabe = raw_input("Eingabe: ")
		
		if eingabe == "q":
			cls()
			exit(0)
		elif eingabe == "1":
			cls()
			dreieck()
			break
		elif eingabe == "2":
			cls()
			dreieck()
			break
		elif eingabe == "3":
			cls()
			dreieck()
			break
		elif eingabe == "4":
			cls()
			dreieck()
			break
		elif eingabe == "5":
			cls()
			dreieck()
			break
		else:
			cls()
			print("Der Befehl '%s' wurde nicht gefunden. bitte erneut eingeben.") % eingabe
			newLine(1)


########################################################################
########################################################################


def dreieck():	# Dreiecksfunktion - Menü
	while 1:
		print("Verfügbare Dreiecksfunktionen:\n\n"
			"[1] allgemeines Dreieck (Oberfläche)\n"
			"[2] allgemeines Dreieck (Umfang)\n"
			"[3] rechtwinkliges Dreieck (Seitenberechnung)\n\n"
			"'m' eingeben um in das Hauptmenü zu kommen.\n"
			"'q' eingeben, um das Programm zu beenden.\n")

		eingabe = raw_input("Eingabe: ")
		
		if eingabe == "q":
			cls()
			exit(0)
		elif eingabe == "m":
			cls()
			menu()
		elif eingabe == "1":
			cls()
			dreieck1(1)
			break
		elif eingabe == "2":
			cls()
			dreieck1(2)
			break
		elif eingabe == "3":
			cls()
			dreieck1(3)
			break
		else:
			cls()
			print("Der Befehl '%s' wurde nicht gefunden. bitte erneut eingeben.") % eingabe
			newLine(1)




	###################################################################
	##                     Dreiecks - Funktionen                     ##
	###################################################################




"""

mode 1 = allgemeines Dreieck (Oberfläche)
mode 2 = allgemeines Dreieck (Umfang)
mode 3 = rechtwinkliges Dreieck (Seitenberechnung)

"""




def dreieck1(mode, errormsg = "", einheit = ""):
	
########################################################################
########################################################################
	
	
	if mode == 1: # Allgemeines Dreieck (Oberfläche)
		
		while 1:
			
			if errormsg == "":
				newLine(0)
			else:
				print(errormsg + "\n")
				

			eingabe = raw_input("Gebe bitte die benötigte Einheit ein:\n"
								"Möglich: " + str(UNITS[0:len(UNITS)]) + "\n\n"
								"Einheit: ")
			cls()
			A = int(raw_input("Gebe bitte die Oberfläche an:\n\nA = "))
			cls()
			g = int(raw_input("Gebe bitte die Grundseite an:\n\ng = "))
			cls()
			h = int(raw_input("Gebe bitte die Höhe an:\n\nh = "))
			cls()
	
			if g == 0 or g == 0.0: # Falls 'g' gesucht
				if A == 0 or A == 0.0 or h == 0 or h == 0.0:
					cls()
					dreieck1(1, ERRORMSG_ONELEFT2) # 'dreieck1'-Funktion in 'modus 1' starten
					break
				else:
					g = 2*A/h
					cls()
					print("g = " + str(g) + " " + str(unit(1)))
					newLine(1)
					dreieck()
					break
					
			elif A == 0 or A == 0.0: # Falls 'A' gesucht
				if g == 0 or g == 0.0 or h == 0 or h == 0.0:
					cls()
					dreieck1(1, ERRORMSG_ONELEFT2)
					break
				else:
					A = g*h/2
					cls()
					einheit = unit(2)
					print("A = " + str(A) + " " + str(unit(2)))
					newLine(1)
					dreieck()
					break
					
			elif h == 0 or h == 0.0: # Falls 'h' gesucht
				if A == 0 or A == 0.0 or g == 0 or g == 0.0:
					cls()
					dreieck1(1, ERRORMSG_ONELEFT2)
					break	
				else:
					h = 2*A/g
					cls()
					einheit = unit(1)
					print("h = " + str(h) + " " + str(unit(1)))
					newLine(1)
					dreieck()
					break
					
			else:
				cls()
				dreieck1(1, ERRORMSG_ONELEFT)
				break	
				
			cls()

########################################################################
########################################################################

	elif mode == 2: # Allgemeines Dreieck (Umfang)
		
		while 1:
			
			if errormsg == "":
				newLine(0)
			else:
				print(errormsg + "\n")


			u = int(raw_input("Gebe bitte den Umfang an:\n\nu = "))
			cls()
			a = int(raw_input("Gebe bitte die Seite 'a' an:\n\na = "))
			cls()
			b = int(raw_input("Gebe bitte die Seite 'b' an:\n\nb = "))
			cls()
			c = int(raw_input("Gebe bitte die Seite 'c' an:\n\nc = "))
			cls()
			
			if u == 0 or u == 0.0: # Falls u gesucht
				if a == 0 or a == 0.0 or b == 0 or b == 0.0 or c == 0 or c == 0.0:
					cls()
					dreieck1(2, ERRORMSG_ONELEFT2)
					break
				else:
					u = a + b + c
					cls()
					print("u = " + str(u))
					newLine(1)
					dreieck()
					break
					
			elif a == 0 or a == 0.0: # Falls a gesucht
				if u == 0 or u == 0.0 or b == 0 or b == 0.0 or c == 0 or c == 0.0:
					cls()
					dreieck1(2, ERRORMSG_ONELEFT2)
					break
				else:
					a = u - b - c
					cls()
					print("a = " + str(a))
					newLine(1)
					dreieck()
					break
					
			elif b == 0 or b == 0.0: # Falls b gesucht
				if u == 0 or u == 0.0 or a == 0 or a == 0.0 or c == 0 or c == 0.0:
					cls()
					dreieck1(2, ERRORMSG_ONELEFT2)
					break
				else:
					b = u - a - c
					cls()
					print("b = " + str(b))
					newLine(1)
					dreieck()
					break
					
			elif c == 0 or c == 0.0: # Falls c gesucht
				if u == 0 or u == 0.0 or b == 0 or b == 0.0 or a == 0 or a == 0.0:
					cls()
					dreieck1(2, ERRORMSG_ONELEFT2)
					break
				else:
					c = a + b + c
					cls()
					print("c = " + str(c))
					newLine(1)
					dreieck()
					break
					
			else:
				cls()
				dreieck1(1, ERRORMSG_ONELEFT)
				break	
				
			cls()

########################################################################
########################################################################

	elif mode == 3: # rechtwinkliges Dreieck (Seitenberechnung)

		while 1:
			
			if errormsg == "":
				newLine(0)
			else:
				print(errormsg + "\n")


			c = int(raw_input("Gebe bitte die Seite 'c' an:\n\nc = "))
			cls()
			a = int(raw_input("Gebe bitte die Seite 'a' an:\n\na = "))
			cls()
			b = int(raw_input("Gebe bitte die Seite 'b' an:\n\nb = "))
			cls()
			
			if c == 0 or c == 0.0: # Falls c² gesucht
				if a == 0 or a == 0.0 or b == 0 or b == 0.0:
					cls()
					dreieck1(2, ERRORMSG_ONELEFT2)
					break
				else:
					c = math.sqrt(a^2 + b^2)
					cls()
					print("c = " + str(c))
					newLine(1)
					dreieck()
					break
					
			if a == 0 or a == 0.0: # Falls a² gesucht
				if b == 0 or b == 0.0 or c == 0 or c == 0.0:
					cls()
					dreieck1(2, ERRORMSG_ONELEFT2)
					break
				else:
					a = math.sqrt(c^2 - b^2)
					cls()
					print("b = " + str(b))
					newLine(1)
					dreieck()
					break

			if b == 0 or b == 0.0: # Falls b² gesucht
				if a == 0 or a == 0.0 or c == 0 or c == 0.0:
					cls()
					dreieck1(2, ERRORMSG_ONELEFT2)
					break
				else:
					b = math.sqrt(c^2 - a^2)
					cls()
					print("b = " + str(b))
					newLine(1)
					dreieck()
					break	

			else:
				cls()
				dreieck1(1, ERRORMSG_ONELEFT)
				break	
								
				
			cls()




########################################################################
########################################################################




if __name__ == "__main__":

	menu ()
Zuletzt geändert von Anonymous am Donnerstag 2. Juni 2016, 23:44, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
BlackJack

@Reboot21: Zeig am besten mal den tatsächlichen Quelltext, denn der hier kommt nicht am Compiler vorbei weil der ausgerechnet in der `unit()`-Funktion einen Einrückfehler hat. Wenn man den behebt, kommt gleich das nächste Problem, nämlich das dort `eingabe` verwendet wird, das aber gar nicht definiert ist. So magisch aus der Umgebung irgendwelche Variablen benutzen ist sowieso keine gute Idee. Werte, ausser Konstanten, sollten Funktionen und Methoden als Argumente betreten und gegebenfalls als Rückgabewerte verlassen. ``global`` hat dementsprechend in einem sauberen Programm nichts zu suchen. Auf Modulebene hat es zudem überhaupt keinen Effekt.

Programmfehler: Der ^-Operator macht nicht das was Du denkst. Das ist die bitweise exklusiv-oder-Verknüpfung. ``x^2`` schaltet das zweite Bit, vom niederwertigsten aus gesehen, um. Also falls es gesetzt war ist es im Ergebnis nicht gesetzt und umgekehrt.

`sys` wird importiert, aber nicht verwendet.

Namen sollte man nicht durchnummerieren. Dann will man in der Regel entweder eine Datenstruktur verwenden, meistens eine Liste, oder sich passendere Namen ausdenken.

Ferner sollte man Namen nicht abkürzen. Insbesondere wenn man Kommentare schreibt um an verschiedenen Stellen zu erklären was der nichtssagende Namen *eigentlich* bedeuten soll. Wenn Du `n` bei `unit()` gleich `potenz` genannt hättest, hättest Du Dir drei Kommentare sparen können die dem Leser sagen, dass es sich bei `n` um die Potenz handelt.

`unit()` ist kein guter Name für eine Funktion. Funktionen *tun* etwas, weshalb man sie üblicherweise nach den Tätigkeiten benennt die sie durchführen. Dann weiss der Leser das beim lesen des Namens und man kann Funktionsnamen auch leichter von Namen für eher ”passive” Dinge unterscheiden. An der Stelle wäre mal interessant zu erfahren was diese Funktion eigentlich machen soll. Welche Wertebereiche sind bei den Argumenten erlaubt, zu welchen Rückgabewerten soll das jeweils führen, und was passiert Deiner Meinung nach bei Werten ausserhalb des erlaubten Bereichs. Und warum ist das so gelöst wie es gelöst ist. Kannst Du mal die tatsächliche Funktion einen Beispielaufruf zeigen bei dem Du `None` als Ergebnis bekommst, aber etwas anderes erwartet hast? Und erklären *warum* Du etwas anderes erwartet hast?

``for i in range(0, len(sequence)):`` nur um dann die Laufvariable als Index in die Sequenz zu verwenden ist in Python ein „anti pattern“. Man kommt fast immer ohne solche Index-Laufvariablen aus. Ich verstehe an der Stelle aber sowieso nicht wozu diese Schleife gut sein soll wenn das gefundene als (Teil des) Rückgabewerts verwendet wird, aber man das ja bereits unter dem Namen `eingabe` hat. Also wenn es diesen Namen denn geben würde. Falls Du prüfen wolltest ob `eingabe` einem Wert in `UNIT` entspricht, hätte man das auch ganz einfach mit dem ``in``-Operator prüfen können. Dann wäre aber die Frage was dann passieren soll, und wie gesagt, *was soll diese Funktion eigentlich leisten*‽

Da Du auf komplett auf UTF-8 setzt, also letztendlich komplett Unicode abdeckst: Es gibt alle Ziffern von 0 bis 9 auch als hochgestellte Variante in Unicode, nicht nur 2 und 3. Man könnte also eine Funktion schreiben die jedes `n` umwandelt.

Der Name `newLine()` beschreibt keine Tätigkeit und entspricht in der Schreibweise nicht dem Style Guide for Python Code. Die Argumente für `range()` sind unnötig kompliziert weil ein ``range(n)`` den gleichen Effekt hat. Das `n` dann auch noch mal als Laufvariable verwendet wird ist verwirrend. Für Schleifen die nur der Wiederholungen wegen verwendet werden benutzt man üblicherweise `_` als Namen für die Laufvariable. Das ist der konventionelle Name für „ich muss hier aus syntaktischen Gründen einen Namen angeben der aber nicht verwendet wird“.

Das ist Python 2, da ist ``print`` eine Anweisung und keine Funktion. Dementsprechend sollte man das auch nicht wie eine Funktion schreiben. Denn spätestens wenn man dieser nicht-Funktion mehr als ein Argument übergeben will, verhält sich das plötzlich nicht mehr so wie man das erwartet hat. Wenn es eine Funktion wäre, würdest Du auch einen Laufzeitfehler in Zeile 92 bekommen, weil sich der ``%``-Operator dann nicht auf die Zeichenkette mit den überflüssigen Klammern beziehen würde, sondern auf den Rückgabewert der Funktion.

Bei `menu()` ist wieder der Kommentar überflüssig wenn man die Funktion gleich entsprechend benennen würde.

Python kennt einen booleschen Datentyp und Wahrheitswerte von diesem Typ. Wenn man `True` oder `False` meint, sollte man nicht 1 oder 0 verwenden.

Wenn in *jedem* Zweig eines ``if``/``elif``/``else``-Konstrukts am Anfang und/oder am Ende das gleiche gemacht wird, dann kann man das auch *einmal* davor beziehungsweise danach schreiben, statt es in jedem Zweig zu wiederholen.

Das Hauptmenü lügt. Da kommt ja bei jedem Punkt die Dreiecksberechnung. Buuuh. :-)

Da Funktionen in Python Werte sind, kann man solche Menüs mit Datenstrukturen einfacher und kompakter ausdrücken und es wird dann auch leichter veränder- und erweiterbar. (Da kommt sicher noch ein Link von einem anderen Benutzer zu einem Beispiel.)

``exit(0)`` sollte eigentlich ``sys.exit()`` heissen. Das die `exit()`-Funktion ohne importieren verfügbar ist, ist nicht dokumentiert, also sollte man sich nicht darauf verlassen.

`dreieck()` ist wieder ein unpassender Name für eine Funktion. Genau wie `dreieck1()`. Wenn man denen die Namen gibt die beschreiben was die Funktionen tun, hätte man nicht diese unsinnige Nummer anhängen müssen.

(Mehrzeilige) Zeichenketten sind keine Kommentare! Missbrauche die nicht dafür. An bestimmten Stellen kann man sie zur Dokumentation verwenden, aber nur dort sollte man sie auch schreiben.

”Magische” Zahlwerte sollte man vermeiden. Statt der Zahlen wie für `mode` sollte man sich mindestens Konstanten mit sprechenden Bezeichnern anlegen.

Allerdings ist dieses `mode` ein „code smell“. Die Funktion führt je nach Wert dieses Arguments drei völlig unterschiedliche Berechnungen durch. Das sind also eigentlich drei verschiedene Funktionen, denn eine Funktion sollte möglichst eine klar abgegrenzte Aufgabe erledigen. Und dabei auch nicht zu lang werden. Ein paar Zeilen sind okay, ab 25 wirds in der Regel brenzlig, und über 50 ist normalerweise zu lang. Da gibt es natürlich Ausnahmen, zum Beispiel bei Funktionen die zwar lang, aber einfach sind.

Was wäre denn eine ganze Zahl die bei ``g == 0 or g == 0.0`` *nicht* *beide* Bedingungen erfüllt. Also welche Zahl ist ungleich 0 aber gleich 0.0?

Was denkst Du was ``newLine(0)`` bewirkt? Und was das „slicen“ von `UNITS` in ``str(UNITS[0:len(UNITS)])``? Und warum so umständlich mit 0 und ``len(UNITS)``?

Das Zusammenstückeln von Zeichenketten und Werten mit `str()` und ``+`` ist eher BASIC als Python. Den ``%``-Operator kennst Du doch bereits. Wobei man das mittlerweile eher mit der `format()`-Methode auf Zeichenketten erledigt.

Das mit dem rekursiven Aufruf von `dreieck1()` mit einem Wert für `errormsg` würde ich als Programmfehler ansehen. Du schreibst hier ohne Not eine Rekursion als Ersatz für eine Schleife. Das geht nicht beliebig lange gut, irgendwann bricht das Programm mit einer Fehlermeldung ab, und ausserdem ist das total undurchsichtig.

Prüfe am besten gleich nach der Eingabe wieviele Angaben fehlen beziehungsweise 0 sind und wenn das mehr als eine ist, dann fang gar nicht erst mit der Berechnung an. Negative Werte sollte man an der Stelle vielleicht auch nicht annehmen.

Insgesamt ist das alles sehr viel Schreibarbeit beziehungsweise viele sehr ähnliche Code-Wiederholungen die man mit einer allgemeineren Lösung und Datenstrukturen viel kürzer und leichter Erweiterbar hinbekommt. Stell Dir mal vor wieviel von diesem Code Du noch schreiben musst für Viereck, Vieleck, Kreis, und Körper. Das macht doch keinen Spass.
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

@BlackJack: ² und ³ sind noch im ANSI-Zeichensatz. Alle anderen Ziffern würden unter Windows Probleme machen. Aber da es so schön ist »dm⁻⁷« zu schreiben:

Code: Alles auswählen

UNITS = ["mm", "cm", "dm", "m", "km", "ha"]
SUPERSCRIPT_DIGITS = u"⁰¹²³⁴⁵⁶⁷⁸⁹"

def unit_to_string(einheit, potenz):
    if einheit not in UNITS:
        raise ValueError("{} not in units".format(einheit))
    return u"{}{}{}".format(einheit, u'⁻' if potenz < 0 else u'',
        u''.join(hoch[int(x)] for x in str(abs(potenz)))
    )
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

Ich glaube beliebig tief verschachtelte Menüs hatten wir hier noch nicht so viele:

Code: Alles auswählen

def run_menu(menu):
    menu_stack = []
    while True:
        print "Verfügbare Programme:\n"
        for idx, (title, _) in enumerate(menu, 1):
            print "[{}] {}".format(idx, title)
        print
        if menu_stack:
            print "'m' eingeben um in das übergeordnete Menü zu kommen."
        print "'q' eingeben, um das Programm zu beenden."
        print
        eingabe = raw_input("Eingabe: ")
        cls()
        if eingabe == "q":
            return
        elif eingabe == "m" and menu_stack:
            menu = menu_stack.pop()
        elif eingabe.isdigit() and 1 <= int(eingabe) <= len(menu):
            _, action = menu[int(eingabe) - 1]
            if isinstance(action, list):
                menu_stack.append(menu)
                menu = action
            else:
                action()
        else:
            print "Der Befehl '{}' wurde nicht gefunden. bitte erneut eingeben.".format(eingabe)
            print
 
MENU = [
    ("Dreiecksberechnung", [
        ("allgemeines Dreieck (Oberfläche)", dreieck_flaeche),
        ("allgemeines Dreieck (Umfang)", dreieck_umfang),
        ("rechtwinkliges Dreieck (Seitenberechnung)", dreieck_seiten),
    ]),
    ("Viereckberechnung", []),
    ("Vieleckberechnung", []),
    ("Kreisberechnung", []),
    ("Körperberechnung", []),
]

if __name__ == '__main__':
    run_menu(MENU)
Reboot21
User
Beiträge: 6
Registriert: Donnerstag 2. Juni 2016, 21:42

Moin,

ich hatte mich noch einmal darangesetzt und konnte das Problem selbst lösen.
Ich bedanke mich auf jeden Fall schon einmal für eure Antworten. Hätte nicht gedacht, dass hier jemand so schnell antwortet..

Hier erst einmal mein jetziger Code:

Code: Alles auswählen

import math, cls, newLine

global newLine, ERRORMSG_ONELEFT, ERRORMSG_ONELEFT2

cls = cls.cls
newLine = newLine.newLine

UNITS = ["mm", "cm", "dm", "m", "km", "ha"]
ERRORMSG_ONELEFT = "Es sollte nur ein Wert fehlen!"
ERRORMSG_ONELEFT2 = "Es kann nur ein fehlender Wert errechnet werden!"




	#####################################################################
	##                     Allgemeine - Funktionen                     ##
	#####################################################################




def potenz(_, eingabe = ""):
		
	for i in range(0, len(UNITS)): # Von 0 bis zur Länge der Einheit-Liste ('Items') 
		if eingabe == UNITS[i]: # Falls 'eingabe' = das i'te Objekt in UNITS
			if _ == 1: # Falls potenz = 1
				return UNITS[i]
			elif _ == 2: # Falls potenz = 2
				return UNITS[i] + "²"
			elif _ == 3: # Falls potenz = 3
				return UNITS[i] + "³"




	###############################################################
	##                     Menü - Funktionen                     ##
	###############################################################



"""
MENU 1 = Hauptmenü
MENU 2 = Dreiecksfunktionen
"""


def run_menu(MENU): 
	
	if MENU == 1: # Hauptmenü
	
		while True:	
			
			
			print("Verfügbare Programme:\n\n"
				"[1] Dreiecksberechnung\n"
				"[2] Viereckberechnung\n"
				"[3] Vieleckberechnung\n"
				"[4] Kreisberechnung\n"
				"[5] Körperberechnung\n\n"
				"'q' eingeben um das Programm zu beenden.\n")
	   
			eingabe = raw_input("Eingabe: ")
		
			cls()
		
			if eingabe == "q":
				exit(0)
			elif eingabe == "1":
				run_menu(2)
			else:
				print("Der Befehl '{}' wurde nicht gefunden. bitte erneut eingeben.".format(eingabe))
				newLine(1)
				run_menu(1)
			
			break
			cls()


########################################################################
########################################################################

	elif MENU == 2: # Dreiecksfunktionen
		
		while True:
			
			print("Verfügbare Dreiecksfunktionen:\n\n"
				"[1] allgemeines Dreieck (Oberfläche)\n"
				"[2] allgemeines Dreieck (Umfang)\n"
				"[3] rechtwinkliges Dreieck (Seitenberechnung)\n\n"
				"'m' eingeben um ins übergeordnete Menü zu gelangen.\n"
				"'q' eingeben um das Programm zu beenden.\n")

			eingabe = raw_input("Eingabe: ")
		
			cls()
		
			if eingabe == "q":
				return
			elif eingabe == "m":
				run_menu(1)
			elif eingabe == "1":
				dreieckberechnung(1)
			elif eingabe == "2":
				dreieckberechnung(2)
			elif eingabe == "3":
				dreieckberechnung(3)
			else:
				cls()
				print("Der Befehl '{}' wurde nicht gefunden. bitte erneut eingeben.".format(eingabe))
				newLine(1)
				run_menu(2)

			break
			cls()



	###################################################################
	##                     Dreiecks - Funktionen                     ##
	###################################################################




"""

mode 1 = allgemeines Dreieck (Oberfläche)
mode 2 = allgemeines Dreieck (Umfang)
mode 3 = rechtwinkliges Dreieck (Seitenberechnung)

"""




def dreieckberechnung(mode, einheit = ""):
	
########################################################################
########################################################################
	
	
	if mode == 1: # Allgemeines Dreieck (Oberfläche)
		
		while 1:
				
			eingabe = raw_input("Gebe bitte die benötigte Einheit ein:\n"
								"Möglich: {}\n\n"
								"Einheit: ".format(str(UNITS)))
			cls()
			A = int(raw_input("Gebe bitte die Oberfläche an:\n\nA = "))
			cls()
			g = int(raw_input("Gebe bitte die Grundseite an:\n\ng = "))
			cls()
			h = int(raw_input("Gebe bitte die Höhe an:\n\nh = "))
			cls()
	
			if g == 0: # Falls 'g' gesucht
				if A == 0 or h == 0:
					dreieckberechnung(1)
				else:
					g = 2*A/h
					print("g = " + str(g) + " " + str(potenz(1, eingabe)))
					newLine(1)
					run_menu(2)
					
			elif A == 0: # Falls 'A' gesucht
				if g == 0 or h == 0:
					dreieckberechnung(1)
				else:
					A = g*h/2
					print("A = " + str(A) + " " + str(potenz(2, eingabe)))
					newLine(1)
					run_menu(2)
					
			elif h == 0: # Falls 'h' gesucht
				if A == 0 or g == 0:
					dreieckberechnung(1)	
				else:
					h = 2*A/g
					print("h = " + str(h) + " " + str(potenz(1, eingabe)))
					newLine(1)
					run_menu(2)
					
			else:
				dreieckberechnung(1)	
				
			cls()
			break

########################################################################
########################################################################

	elif mode == 2: # Allgemeines Dreieck (Umfang)
		
		while 1:

			eingabe = raw_input("Gebe bitte die benötigte Einheit ein:\n"
								"Möglich: {}\n\n"
								"Einheit: ".format(str(UNITS)))
			cls()
			u = int(raw_input("Gebe bitte den Umfang an:\n\nu = "))
			cls()
			a = int(raw_input("Gebe bitte die Seite 'a' an:\n\na = "))
			cls()
			b = int(raw_input("Gebe bitte die Seite 'b' an:\n\nb = "))
			cls()
			c = int(raw_input("Gebe bitte die Seite 'c' an:\n\nc = "))
			cls()
			
			
			if u == 0: # Falls u gesucht
				if a == 0 or b == 0 or c == 0:
					dreieckberechnung(2)
				else:
					u = a + b + c
					print("u = " + str(u) + " " + potenz(1, eingabe))
					newLine(1)
					run_menu(2)
					
			elif a == 0: # Falls a gesucht
				if u == 0 or b == 0 or c == 0:
					dreieckberechnung(2)
				else:
					a = u - b - c
					print("a = " + str(a) + " " + potenz(1, eingabe))
					newLine(1)
					run_menu(2)
					
			elif b == 0: # Falls b gesucht
				if u == 0 or a == 0 or c == 0:
					dreieckberechnung(2)
				else:
					b = u - a - c
					print("b = " + str(b) + " " + potenz(1, eingabe))
					newLine(1)
					run_menu(2)
					
			elif c == 0: # Falls c gesucht
				if u == 0 or b == 0 or a == 0:
					dreieckberechnung(2)
				else:
					c = a + b + c
					print("c = " + str(c) + " " + potenz(1, eingabe))
					newLine(1)
					run_menu(2)
					
			else:
				dreieckberechnung(1)	
				
			cls()
			break

########################################################################
########################################################################

	elif mode == 3: # rechtwinkliges Dreieck (Seitenberechnung)

		while 1:
			
			eingabe = raw_input("Gebe bitte die benötigte Einheit ein:\n"
								"Möglich: {}\n\n"
								"Einheit: ".format(str(UNITS)))
			cls()
			c = int(raw_input("Gebe bitte die Seite 'c' an:\n\nc = "))
			cls()
			a = int(raw_input("Gebe bitte die Seite 'a' an:\n\na = "))
			cls()
			b = int(raw_input("Gebe bitte die Seite 'b' an:\n\nb = "))
			cls()
			
			if c == 0: # Falls c² gesucht
				if a == 0 or b == 0:
					dreieckberechnung(2)
				else:
					c = math.sqrt(a**2 + b**2)
					print("c = " + str(c) + " " + potenz(1, eingabe))
					newLine(1)
					run_menu(2)
					
			if a == 0: # Falls a² gesucht
				if b == 0 or c == 0:
					dreieckberechnung(2)
				else:
					a = math.sqrt(c**2 - b**2)
					print("b = " + str(b) + " " + potenz(1, eingabe))
					newLine(1)
					run_menu(2)

			if b == 0: # Falls b² gesucht
				if a == 0 or c == 0:
					dreieckberechnung(2)
				else:
					b = math.sqrt(c**2 - a**2)
					print("b = " + str(b) + " " + potenz(1, eingabe))
					newLine(1)
					run_menu(2)
			else:
				dreieckberechnung(1)
								
				
			cls()
			break




########################################################################
########################################################################




if __name__ == "__main__":

	run_menu(1)
@BlackJack:

Die Funktion unit() heißt jetzt potenz() und soll durch zwei Argumente (Das erste ist die benötigte Potenz (¹,²,³), das zweite soll die Eingabe der Einheit angeben. In dieser Funktion wird anhand der Argumente die entsprechende Einheit mit Potenz ausgegeben, falls nötig.
Also wenn ich die Funktion mit

Code: Alles auswählen

potenz(2, eingabe)


aufrufe und davor mit input in die Variable eingabe z.B. cm hineingeschrieben habe,
dann gibt diese Funktion dementsprechend nach dem ersten Argument 'cm²' aus, was dann weiterverwendet werden kann.

Der Einrückfehler muss beim einfügen des Codes passiert sein..
Wie man oben sehen kann habe ich das bei der Funktion unit() jetzt so wie von dir beschrieben gemacht,
dass der Eingangswert Funktion über ein Argument betritt und entsprechend als return-Wert verlässt.
Das mit den ^ Operator war ein kleiner Denkfehler von mir, es sollte natürlich '**' sein. ;)
Das mit dem sys import hatte ich übersehen aber jetzt behoben.
Zudem habe ich jetzt auch unit() in potenz() umbenannt. (Finde ich auch besser)
Und das mit dem Hauptmenü habe ich nur für spätere Einträge gemacht.

newLine(0) bewirkt garnichts. Das weiß ich auch :)
Ich hatte es als schlechten Platzhalter benutzt. Sollte ich mir abgewöhnen.
Und das mit dem slicen von str(UNITS[0:len(UNITS)]) war ein Denkfehler von mir.

Das Prüfen der Eingaben, sowie die suche nach einer allgemeinen Lösung käme als nächstes dran.
Als erstes mache ich immer das Basisprogramm (in dem Fall die erste Berechnungsart), welches ich dann am Schluss "komprimiere".

@Sirius3:

Mit deinem Code kann ich leider nicht viel Anfangen,
da ich die meisten Funktionen, die du dort verwendet hast, garnicht kenne.
Ich werde es mir aber einmal anschauen.

------

Wie ihr sehen könnt und erkannt habt, bin ich noch ein ziemlicher Anfänger. Ehem. komme ich von Visual Basic, da ich allerdings etwas Plattformunabhängiger (kein Java) programmieren wollte, habe ich mich für Python entschieden.

Frage so mal am Rand: Welches Python Tutorial könnt ihr mir so empfehlen?

Mfg

Reboot21
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

@Reboot21: was ist jetzt an dem Parameternamen »_« besser als bei »n«? Alle anderen Hinweise von BlackJack scheinst Du auch in die schlimmere Richtung geändert zu haben. Was sind denn die Module cls und newLine? Das sind hoffentlich keine Module die jeweils nur aus einer Funktion bestehen.
Wenn man einen Namen aus einem Modul importieren will, macht man das auch

Code: Alles auswählen

# nicht so
import cls
cls = cls.cls

# sondern so
from cls import cls
Statt magische Zahlenwerte loszuwerden hast Du bei run_menu noch einen zusätzlichen eingefügt. Eine Funktion sollte *eine* Sache machen und zwar richtig, und nicht 3 oder 4 verschiedene.

Rekursion ist kein Ersatz für eine Schleife, zumal die vorhanden while-Schleife kaputt ist, da sie immer nach dem ersten Durchgang per break verlassen wird. Alles was nach break steht wird auch nicht mehr ausgeführt.
Reboot21
User
Beiträge: 6
Registriert: Donnerstag 2. Juni 2016, 21:42

Danke für den Hinweis mit dem importieren des Moduls. Auch da hatte ich einen Fehler gemacht.
Anscheinend habe ich eure Instruktionen/Anregungen falsch interpretiert.
Ich versuche mein Bestes was diese Sache angeht.
Nur ist es schwer die Dinge, die einen gesagt werden als Anfänger auch umzusetzen, wenn man so mit Informationen sprichwörtlich "zugebombt" wird.
Jedoch ist dies meine Schuld, da ich am Anfang schon meinte, dass man mir ruhig Verbesserungsvorschläge machen kann.
Ich weiß auch garnicht so richtig, was du jetzt an dem Parameter '_' bei potenz() so schlimm findest.
newLine und cls waren zwei Module, richtig..
Recht hast du damit. Ist ja auch schwachsinnig zwei versch. Module mit jeweils einer Funktion..
Sirius3 hat geschrieben:Alle anderen Hinweise von BlackJack scheinst Du auch in die schlimmere Richtung geändert zu haben.
Das hilft mir nicht gerade. Ich weiß, dass ihr das in eurer Freizeit macht, genauso wie ich in meiner Freizeit programmiere,
zumindestens versuche ich es. :/

Letztenendes versuche ich doch auch nur das umzusetzen, was ihr mir gibt.

Mfg


Reboot21
BlackJack

@Reboot21: Was an `_` als Argumentname schlimm ist? Namen sollen dem Leser wie schon gesagt vermitteln was der Wert bedeutet. Was soll denn `_` bitte bedeuten? Zumal das, wie ich ja auch geschrieben hatte, per Konvention der Name für Werte ist, die man nicht verwendet, wo man aber aus syntaktischen Gründen einen Namen schreiben muss. Dieser Name wird in der Funktion aber verwendet. Und die Kommentare stehen da ja immer noch damit man weiss das `_` jetzt statt `n` für *potenz* stehen soll. Der Funktionsname ist mit `potenz` auch nicht wirklich besser geworden, weil mir auch da beim Namen nicht klar ist was die Funktion denn nun eigentlich tut. `eingabe` ist ebenfalls kein guter Name, denn auch der beschreibt den Wert nicht wirklich. Zudem macht der Defaultwert (leere Zeichenkette) keinen wirklichen Sinn weil das ja keine gültiger/sinnvoller Wert ist.

Ich habe auch immer noch nicht verstanden warum die Funktion so arbeitet wie sie arbeitet. Ich habe denke ich verstanden was sie tun sollte, aber die Umsetzung ist komisch. Letztlich hast Du an der Arbeitsweise nichts geändert, das heisst die führt immer noch zu dem Problem aus dem Ausgangsbeitrag. Die Schleife und `eingabe` machen da nicht wirklich Sinn. Und die Schleife verwendet immer noch einen unnötigen Laufindex.
Reboot21
User
Beiträge: 6
Registriert: Donnerstag 2. Juni 2016, 21:42

Ich habe auch immer noch nicht verstanden warum die Funktion so arbeitet wie sie arbeitet. Ich habe denke ich verstanden was sie tun sollte, aber die Umsetzung ist komisch.
Die Funktion soll halt die Potenz individuell für die Ausgabe bestimmen.
Zum Beispiel brauch man bei der Oberfläche ², jedoch bei Volumen ³.
Das ist im Prinzip das einzige, was diese Funktion macht.
Ich wollte halt nicht immer wieder Abfragen, welche Potenz nun nötig ist.
Zudem weiß ich nicht, wie ich das mit

Code: Alles auswählen

for i in UNITS:
	...
bewerkstelligen soll..

Ich habe den Code jetzt noch einmal überarbeitet, jedoch nichts zusammengefasst, da ich gerade auch nicht weiß wie ich das bewerkstelligen soll.

Falls ihr den Schund noch einmal sehen wollt :roll:

Code: Alles auswählen

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


import math, sys
from extfunctions import cls, newLine


UNITS = ["mm", "cm", "dm", "m", "km", "ha"]




	#####################################################################
	##                     Allgemeine - Funktionen                     ##
	#####################################################################




def EinheitBestimmung(potenz, einheit):
	
	for i in range(0, len(UNITS)):
	
		if einheit == UNITS[i]:
			if potenz == 1: # Falls potenz = 1
				return UNITS[i]
			elif potenz == 2: # Falls potenz = 2
				return UNITS[i] + "²"
			elif potenz == 3: # Falls potenz = 3
				return UNITS[i] + "³"
			else:
				return "cm"




	###############################################################
	##                     Menü - Funktionen                     ##
	###############################################################




def menu_main(): 
	
		while True:	
			
			print("Verfügbare Programme:\n\n"
				"[1] Dreiecksberechnung\n"
				"[2] Viereckberechnung\n"
				"[3] Vieleckberechnung\n"
				"[4] Kreisberechnung\n"
				"[5] Körperberechnung\n\n"
				"'q' eingeben um das Programm zu beenden.\n")
	   
			eingabe = raw_input("Eingabe: ")
		
			cls()
		
			if eingabe == "q":
				sys.exit()
			elif eingabe == "1":
				cls()
				menu_dreieck()
			else:
				cls()
				print("Der Befehl '{}' wurde nicht gefunden. Bitte erneut eingeben.".format(eingabe))
				newLine(1)
				continue



def menu_dreieck():
		
	while True:
			
		print("Verfügbare Dreiecksfunktionen:\n\n"
			"[1] allgemeines Dreieck (Oberfläche)\n"
			"[2] allgemeines Dreieck (Umfang)\n"
			"[3] rechtwinkliges Dreieck (Seitenberechnung)\n\n"
			"'m' eingeben um ins übergeordnete Menü zu gelangen.\n"
			"'q' eingeben um das Programm zu beenden.\n")
				
		eingabe = raw_input("Eingabe: ")
		
		cls()
		
		if eingabe == "q":
			sys.exit()
		elif eingabe == "m":
			cls()
			menu_main()
		elif eingabe == "1":
			cls()
			dreieck_oberflaeche()
		elif eingabe == "2":
			cls()
			dreieck_umfang()
		elif eingabe == "3":
			cls()
			dreieck_seiten()
		else:
			cls()
			print("Der Befehl '{}' wurde nicht gefunden. Bitte erneut eingeben.".format(eingabe))
			newLine(1)
			continue




	###################################################################
	##                     Dreiecks - Funktionen                     ##
	###################################################################




def dreieck_oberflaeche():
	
	while True:
		
		eingabe = raw_input("Gebe bitte die benötigte Einheit ein:\n"
						"Möglich: {}\n\n"
						"Einheit: ".format(str(UNITS)))
		cls()
		A = int(raw_input("Gebe bitte die Oberfläche an:\n\nA = "))
		cls()
		g = int(raw_input("Gebe bitte die Grundseite an:\n\ng = "))
		cls()
		h = int(raw_input("Gebe bitte die Höhe an:\n\nh = "))
		cls()
	
		if g == 0: # Falls 'g' gesucht
			if A == 0 or h == 0:
				continue
			else:
				g = 2*A/h
				print("g = {} {}".format(str(g), str(EinheitBestimmung(1, eingabe))))
				newLine(1)
				menu_dreieck()
					
		elif A == 0: # Falls 'A' gesucht
			if g == 0 or h == 0:
				continue
			else:
				A = g*h/2
				print("A = {} {}".format(str(A), str(EinheitBestimmung(2, eingabe))))
				newLine(1)
				menu_dreieck()
					
		elif h == 0: # Falls 'h' gesucht
			if A == 0 or g == 0:
				continue	
			else:
				h = 2*A/g
				print("h = {} {}".format(str(h), str(EinheitBestimmung(1, eingabe))))
				newLine(1)
				menu_dreieck()
					
		else:
			continue




########################################################################
########################################################################




def dreieck_umfang():

	while True:

		eingabe = raw_input("Gebe bitte die benötigte Einheit ein:\n"
							"Möglich: {}\n\n"
							"Einheit: ".format(str(UNITS)))
		cls()
		u = int(raw_input("Gebe bitte den Umfang an:\n\nu = "))
		cls()
		a = int(raw_input("Gebe bitte die Seite 'a' an:\n\na = "))
		cls()
		b = int(raw_input("Gebe bitte die Seite 'b' an:\n\nb = "))
		cls()
		c = int(raw_input("Gebe bitte die Seite 'c' an:\n\nc = "))
		cls()
			
			
		if u == 0: # Falls u gesucht
			if a == 0 or b == 0 or c == 0:
				continue
			else:
				u = a + b + c
				print("u = {} {}".format(str(u), str(EinheitBestimmung(1, eingabe))))
				newLine(1)
				menu_dreieck()
					
		elif a == 0: # Falls a gesucht
			if u == 0 or b == 0 or c == 0:
				continue
			else:
				a = u - b - c
				print("a = {} {}".format(str(a), str(EinheitBestimmung(1, eingabe))))
				newLine(1)
				menu_dreieck()
					
		elif b == 0: # Falls b gesucht
			if u == 0 or a == 0 or c == 0:
				continue
			else:
				b = u - a - c
				print("b = {} {}".format(str(b), str(EinheitBestimmung(1, eingabe))))
				newLine(1)
				menu_dreieck()
					
		elif c == 0: # Falls c gesucht
			if u == 0 or b == 0 or a == 0:
				continue
			else:
				c = a + b + c
				print("c = {} {}".format(str(c), str(EinheitBestimmung(1, eingabe))))
				newLine(1)
				menu_dreieck()
					
		else:
			continue	




########################################################################
########################################################################




def dreieck_seiten():
	
	while True:
	
		eingabe = raw_input("Gebe bitte die benötigte Einheit ein:\n"
							"Möglich: {}\n\n"
							"Einheit: ".format(str(UNITS)))
		cls()
		c = int(raw_input("Gebe bitte die Seite 'c' an:\n\nc = "))
		cls()
		a = int(raw_input("Gebe bitte die Seite 'a' an:\n\na = "))
		cls()
		b = int(raw_input("Gebe bitte die Seite 'b' an:\n\nb = "))
		cls()
			
		if c == 0: # Falls c² gesucht
			if a == 0 or b == 0:
				continue
			else:
				c = math.sqrt(a**2 + b**2)
				print("c = {} {}".format(str(c), str(EinheitBestimmung(1, eingabe))))
				newLine(1)
				menu_dreieck()
					
		if a == 0: # Falls a² gesucht
			if b == 0 or c == 0:
				continue
			else:
				a = math.sqrt(c**2 - b**2)
				print("a = {} {}".format(str(a), str(EinheitBestimmung(1, eingabe))))
				newLine(1)
				menu_dreieck()

		if b == 0: # Falls b² gesucht
			if a == 0 or c == 0:
				continue
			else:
				b = math.sqrt(c**2 - a**2)
				print("b = {} {}".format(str(b), str(EinheitBestimmung(1, eingabe))))
				newLine(1)
				menu_dreieck()
		else:
			continue



########################################################################
########################################################################




if __name__ == "__main__":

	menu_main()
Zuletzt geändert von Anonymous am Freitag 3. Juni 2016, 19:31, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
BlackJack

``for i in UNITS:`` hat schon mal wieder das Problem das `i` der falsche Name ist, denn Namen sollen dem Leser vermitteln was der Wert bedeutet. Nicht das ich das nicht schonmal erwähnt hätte… ;-)

`i` ist okay für ganze Zahlen bei einer Laufvariablen weil man das aus der Mathematik so kennt. Was aber auch bedeutet das so ziemlich jeder Programmierer bei dem Namen `i` in einer Schleife *erwartet* dass das eine ganze Zahl ist. Ist es bei ``for i in UNITS:`` aber nicht.

Wie gesagt, ich denke ich weiss was die Funktion machen soll, nur verstehe ich überhaupt nicht warum sie dass dann nicht tut. Sondern mit dieser komischen Schleife und `UNITS` operiert, und jetzt auch noch unter bestimmten Umständen die Einheit 'cm' zurück gibt, völlig egal welche Einheit man da als Argument übergeben hat. WTF‽ Diese Funktion ist voll schräg und IMHO ist die nicht sinnvoll umgesetzt was das Ergebnis angeht.

Code: Alles auswählen

In [12]: print EinheitBestimmung(1, 'km')
km

In [13]: print EinheitBestimmung(2, 'km')
km²

In [14]: print EinheitBestimmung(3, 'km')
km³

In [15]: print EinheitBestimmung(4, 'km')
cm

In [16]: print EinheitBestimmung(1, 'x')
None
Das ist kein sinnvolles Verhalten.

Und im Beitrag schreibst Du sie soll die Potenz bestimmen, der Name sagt aber sie bestimmt die Einheit. Wie man ganz einfach eine beliebige Potenz in kleinen, hochgestellten Ziffern anhängen kann, hat Sirius3 weiter oben ja schon gezeigt. Das könnte man noch um die Sonderfälle 0 und 1 erweitern.

Ansonsten ist die Funktion aber hier auch ein wenig überflüssig. Denn ob man die Funktion aufruft mit literalen Werten für die Potenz oder von Hand ² oder ³ an die Einheit setzt, nimmt sich letztendlich nicht viel. So eine Funktion würde erst Sinn machen wenn man die Potenz nicht fest im Programm stehen hat, sondern wenn sie berechnet werden würde.
Reboot21
User
Beiträge: 6
Registriert: Donnerstag 2. Juni 2016, 21:42

Ich danke dir erst einmal, dass du es durchgehalten hast, meine Fragen zu beantworten ;)
Zudem ist mir auch vorhin aufgefallen, dass du meinen Code in Python-Quelltext-Tags gesetzt hast.
Ich hatte bezüglich dessen mal nachgeschaut und herausgefunden, dass man das mit

Code: Alles auswählen

[Codebox=python][/Codebox]
machen kann. Wieso ist diese Funktion denn nicht im Editor aufgeführt? :?

Edit: Oops, habe ich wohl im Editor übersehen.

Das die Funktion eigentlich totaler Schwachsinn ist, muss ich dir Recht geben.
Nach einer längeren Pause hatte ich es mir noch einmal angeschaut und hatte selbst gemerkt, wie idiotisch die Sache umgesetzt wurde. :D
Wie sagt man auch: Aller Anfang ist schwer :)

Ich habe es jetzt auf den einfachsten Weg gelöst, wie du auch schon erwähnt hast (Da hatte ich zu kompliziert gedacht).
Wie ich den Code zusammenfasse muss ich noch überlegen.
Und natürlich muss ich noch Ausnahmebehandlungen hinzufügen und vor allem die Variablen etc. Zweckmäßig benennen ;)

Code: Alles auswählen

	while True:
		
		einheit = raw_input("Gebe bitte die benötigte Einheit ein:\n"
						"Möglich: {}\n\n"
						"Einheit: ".format(str(UNITS)))
		cls()
		A = float(raw_input("Gebe bitte die Oberfläche an:\n\nA = "))
		cls()
		g = float(raw_input("Gebe bitte die Grundseite an:\n\ng = "))
		cls()
		h = float(raw_input("Gebe bitte die Höhe an:\n\nh = "))
		cls()
	
		if g == 0: # Falls 'g' gesucht
			if A == 0 or h == 0:
				continue
			else:
				g = 2.0*A/h
				print("g = {} {}".format(str(g), einheit))
				newLine(1)
				menu_dreieck()
					
		elif A == 0: # Falls 'A' gesucht
			if g == 0 or h == 0:
				continue
			else:
				A = g*h/2.0
				print("A = {} {}²".format(str(A), einheit))
				newLine(1)
				menu_dreieck()
					
		elif h == 0: # Falls 'h' gesucht
			if A == 0 or g == 0:
				continue	
			else:
				h = 2.0*A/g
				print("h = {} {}".format(str(h), einheit))
				newLine(1)
				menu_dreieck()
					
		else:
			continue
Zudem habe ich mir die Funktion angeschaut, jedoch verstehe ich gewisse teile nicht.
Wieso wurde die Variable SUPERSCRIPT_DIGITS mit einem u definiert?

Code: Alles auswählen

SUPERSCRIPT_DIGITS = u"⁰¹²³⁴⁵⁶⁷⁸⁹"

    def unit_to_string(einheit, potenz):
        if einheit not in UNITS: 
            raise ValueError("{} not in units".format(einheit)) # Fehlerbehandlung
        return u"{}{}{}".format(einheit, u'⁻' if potenz < 0 else u'',  # Wieso wurde das durch ein Komma getrennt und wieso das '⁻'? 
            u''.join(hoch[int(x)] for x in str(abs(potenz))) # Was bedeutet diese Zeile?

Mfg


Reboot21
BlackJack

Das u vor literalen Zeichenketten gibt an das es sich nicht um eine ”Zeichenkette” (Typ `str`) sondern um eine ”echte” Zeichenkette (Typ `unicode`) handelt. Damit jedes der Zeichen dort auch tatsächlich nur ein Zeichen ist, und nicht wie bei `str` und UTF-8-Kodierung je nach Zeichen ein oder mehr Bytes.

Code: Alles auswählen

In [1]: "⁰¹²³⁴⁵⁶⁷⁸⁹"
Out[1]: '\xe2\x81\xb0\xc2\xb9\xc2\xb2\xc2\xb3\xe2\x81\xb4\xe2\x81\xb5\xe2\x81\xb6\xe2\x81\xb7\xe2\x81\xb8\xe2\x81\xb9'

In [2]: u"⁰¹²³⁴⁵⁶⁷⁸⁹"
Out[2]: u'\u2070\xb9\xb2\xb3\u2074\u2075\u2076\u2077\u2078\u2079'

In [3]: len("⁰¹²³⁴⁵⁶⁷⁸⁹")
Out[3]: 27

In [4]: len(u"⁰¹²³⁴⁵⁶⁷⁸⁹")
Out[4]: 10

In [5]: "⁰¹²³⁴⁵⁶⁷⁸⁹"[5]
Out[5]: '\xc2'

In [6]: print "⁰¹²³⁴⁵⁶⁷⁸⁹"[5]
�

In [7]: u"⁰¹²³⁴⁵⁶⁷⁸⁹"[5]
Out[7]: u'\u2075'

In [8]: print u"⁰¹²³⁴⁵⁶⁷⁸⁹"[5]
⁵
Das Komma ist da weil man Argumente bei Aufrufen durch Kommas trennt. Die Zeichenkette auf der `format()` aufgerufen wird hat drei Platzhalter, also müssen auch drei Argumente übergeben werden.

Das u'⁻' weil man üblicherweise ein Minus vor negative Zahlen setzt.

Der Ausdruck in der letzten Zeile erstellt dann eine Zeichenkette die aus hochgestellten Ziffern besteht.

Das Ganze benutzt Python-Syntax die man lernen müsste. Erraten was das bedeutet ist wahrscheinlich nicht so aussichtsreich.

Und das tolle an Python sind die interaktiven Shells, wie die eingebaute oder auch IPython, wo man Sachen interaktiv ausprobieren kann und sich einfach mal anschauen kann was Teilausdrücke für Teilergebnisse liefern.

Code: Alles auswählen

In [9]: SUPERSCRIPT_DIGITS = u"⁰¹²³⁴⁵⁶⁷⁸⁹"

In [10]: u'⁻' if 42 < 0 else u''
Out[10]: u''

In [11]: u'⁻' if -42 < 0 else u''
Out[11]: u'\u207b'

In [12]: print u'⁻' if -42 < 0 else u''
⁻

In [13]: abs(42)
Out[13]: 42

In [14]: abs(-42)
Out[14]: 42

In [15]: str(abs(-42))
Out[15]: '42'

In [16]: [x for x in str(abs(-42))]
Out[16]: ['4', '2']

In [17]: [int(x) for x in str(abs(-42))]
Out[17]: [4, 2]

In [18]: [SUPERSCRIPT_DIGITS[int(x)] for x in str(abs(-42))]
Out[18]: [u'\u2074', u'\xb2']

In [19]: u''.join([SUPERSCRIPT_DIGITS[int(x)] for x in str(abs(-42))])
Out[19]: u'\u2074\xb2'

In [20]: print u''.join([SUPERSCRIPT_DIGITS[int(x)] for x in str(abs(-42))])
⁴²
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

@Reboot21: das »u« steht für Unicode-Strings. Ohne wären es nur byte-strings mit utf8-codierten Hochzahlen. Solange Dein Terminal auch utf8-codierten Text erwartet, fällt das nicht groß auf, sobald das nicht mehr gilt, bekommst Du seltsame Zeichen (²).

Du benutzt Funktionen immer noch als Springmarken. Eine Funktion sollte eine Aufgabe erledigen (z.B. die Dreiecksfläche berechnen) und danach zum Aufrufer zurückkehren. Du rufst aber aus dreieck_flaeche wieder menu_dreieck auf, statt einfach zurückzukehren.

Die Prüfung, dass zwei Variablen null sind, solltest Du zusammenfassen. Der Aufruf von str ist bei Dir überall überflüssig.
Reboot21
User
Beiträge: 6
Registriert: Donnerstag 2. Juni 2016, 21:42

@BlackJack:

Danke für die gute Erklärung!
Und die interaktiven Shells...
Hatte ich total vergessen, dass man die ja auch dafür verwenden kann. :)

@Sirius3:
Du benutzt Funktionen immer noch als Springmarken. Eine Funktion sollte eine Aufgabe erledigen (z.B. die Dreiecksfläche berechnen) und danach zum Aufrufer zurückkehren. Du rufst aber aus dreieck_flaeche wieder menu_dreieck auf, statt einfach zurückzukehren.
Schon wieder etwas, was ich übersehen habe.. Danke. ich sollte meinen Code sorgfältiger durchlesen, bevor ich ihn hier poste :)
Die Prüfung, dass zwei Variablen null sind, solltest Du zusammenfassen. Der Aufruf von str ist bei Dir überall überflüssig.
Ja, das mache ich noch ;)



Vielen Dank euch beiden!
BlackJack

Das ganze mal ein bisschen generischer und so, dass man das um weitere Formeln erweitern kann ohne grössere Teile an Code zu kopieren:

Code: Alles auswählen

#!/usr/bin/python
# coding: utf8 
from __future__ import absolute_import, division, print_function
import sys
from inspect import getargspec
from math import sqrt

ENCODING = sys.stdout.encoding or sys.getfilesystemencoding()

UNITS = ['mm', 'cm', 'dm', 'm', 'km', 'ha']
POWER_DIGITS = [u'⁰', u'', u'²', u'³']


def ask_unit(units):
    prompt = 'Masseinheit? [{0}]: '.format(','.join(units))
    while True:
        unit = raw_input(prompt)
        if unit in units:
            return unit


class Formula(object):

    def __init__(self, name, description, function, unit_power=1):
        self.name = name
        self.description = description
        self.function = function
        self.unit_power = unit_power

    def __call__(self, arguments):
        return self.function(**arguments)

    @property
    def argument_names(self):
        return getargspec(self.function).args


class Shape(object):

    def __init__(self, description, formulas):
        self.description = description
        self.formulas = formulas
        self.args2formula = dict(
            (tuple(sorted(f.argument_names)), f) for f in formulas
        )

    def get_formula(self, known_arguments):
        return self.args2formula[tuple(sorted(known_arguments.iterkeys()))]


def ask_value(formula):
    prompt = u'{0.description}\n{0.name}='.format(formula).encode(ENCODING)
    while True:
        user_input = raw_input(prompt)
        if not user_input:
            return 0
        try:
            result = float(user_input)
        except ValueError:
            print(user_input, 'ist keine Zahl!')
        else:
            if result < 0:
                print('Bitte eine positive Zahl oder nichts eingeben!')
            else:
                return result


def ask_values(shape):
    print(
        u'Für die Werte bitte positive Zahlen eingeben.\n'
        u'Beim gesuchten Wert 0 oder nichts eingeben.\n'
        u'Leereingabe bei allen Werten führt zurück zum Menü.'
    )
    result = dict()
    for formula in shape.formulas:
        value = ask_value(formula)
        if value:
            result[formula.name] = value
    return result


def calculate_shape(shape, unit):
    print(
        u'{0.description}\n{1}\n'.format(shape, '-' * len(shape.description))
    )
    while True:
        known_arguments = ask_values(shape)
        if not known_arguments:
            return

        try:
            formula = shape.get_formula(known_arguments)
        except KeyError:
            print('Bitte nur eine Angabe frei lassen!')
        else:
            print(
                u'\n{0.description} {0.name}={1:.3f} {2}{3}'.format(
                    formula,
                    formula(known_arguments),
                    unit,
                    POWER_DIGITS[formula.unit_power],
                )
            )
            return


def ask_for_shape(shapes):
    for i, shape in enumerate(shapes, 1):
        print(u'[{0}] {1.description}'.format(i, shape))
    print(u'[z] Zurück')
    while True:
        user_input = raw_input('> ')
        if user_input == 'z':
            return None
        try:
            number = int(user_input)
        except ValueError:
            print('Keine gültige Eingabe!')
        else:
            if not 1 <= number <= len(shapes):
                print(u'Zahl ist kein Menüpunkt.')
            else:
                return shapes[number - 1]


SHAPES = [
    Shape(
        u'Allgemeines Dreieck (Oberfläche)',
        [
            Formula('A', u'Oberfläche', lambda g, h: g * h / 2, 2),
            Formula('g', 'Grundseite', lambda A, h: 2 * A / h),
            Formula('h', u'Höhe', lambda A, g: 2 * A / g),
        ],
    ),
    Shape(
        'Allgemeines Dreieck (Umfang)',
        [
            Formula('u', 'Umfang', lambda a, b, c: a + b + c),
            Formula('a', 'Seite a', lambda u, b, c: u - b - c),
            Formula('b', 'Seite b', lambda u, a, c: u - a - c),
            Formula('c', 'Seite c', lambda u, a, b: u - a - b),
        ]
    ),
    Shape(
        'rechtwinkliges Dreieck (Seitenberechnung)',
        [
            Formula('a', 'Seite a', lambda b, c: sqrt(b**2 - c**2)),
            Formula('b', 'Seite b', lambda a, c: sqrt(a**2 - c**2)),
            Formula('c', 'Seite c', lambda a, b: sqrt(a**2 + b**2)),
        ]
    ),
]



def main():
    while True:
        unit = ask_unit(UNITS)
        shape = ask_for_shape(SHAPES)
        if not shape:
            break
        calculate_shape(shape, unit)


if __name__ == '__main__':
    main()
Blöd ist hier noch, dass man die Formeln selber umstellen und für jede Variable angeben muss. Da könnte man mit `sympy` sicher noch etwas eleganteres hinbekommen.
Antworten