Variablen innerhalb von Klassen & Methoden übergeben

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.
BlackJack

@Hellstorm: Bei `__del__()` wird in den „schlechten” Tutorials ja aber gerade *nicht* erzählt was da passiert, sondern gefährlicher Unsinn und ohne irgendwelche Warnungen welche Garantien (nicht) gegeben werden und was das noch für Folgen haben kann (Speicherlecks). Bis Anfänger mal über ein Problem stolpern wo man tatsächlich `__del__()` sinnvoll verwenden kann, sind sie normalerweise keine Anfänger mehr, und viele werden sogar niemals über so ein Problem stolpern. Warum also Anfänger damit belasten. Das ist IMHO etwas ganz anderes als Anfänger mit einem „das wirst Du später verstehen” abzuspeisen bei Sachen die tatsächlich regelmässig in normalen Programmen zur Anwendung kommen.

Das was man statt `__del__()` häufig verwendet, nämlich Kontextmanager, kommt in Anfängertutorials dagegen sehr selten vor. Mir ist so aus dem Kopf gar keines bekannt. Und für den Zweck *wo* `__del__()` wohl am meisten sinnvoll angewendet wird, nämlich *soweit es halt geht* ”manuelle” Verwaltung von Ressourcen von denen die Python-Laufzeitumgebung nichts weiss, ist Speicherverwaltung bei der Anbindung von externen Bibliotheken mittels `ctypes`. Da muss man dann aber die Speicherverwaltung von Python *und* C ziemlich gut kennen. Trifft auf Anfänger nicht zu.
BSA
User
Beiträge: 38
Registriert: Freitag 6. Dezember 2013, 07:49

Moin Leute,

leicht verspätet, dafür aber ausführlicher, hier nun meine Antworten...

@ BlackJack
1): Ja, mit der eigentlichen Funktion(-sweise) der __init__ und der OOP im Allgemeinen habe ich mich wohl offensichtlich wirklich noch nicht so gut angefreundet...
Daher stelle ich das Thema OOP / Klassen auch erst einmal zurück, und beschäftige mich damit demnächst dann wieder irgendwann, dann allerdings auch von vorne mit kleinen Beispielen/Tuts, Fragen & co.
2): In dem Fall war die Klassenprogrammierung für mich ein Selbstzweck zum Einüben in die OOP, jedoch leicht unsinnig.
Für die OOP muss ich wahrscheinlich nochmal ganz von vorne anfangen und mir entsprechend diverse Tuts/Beiträge/Beispiele anschauen und selber umsetzen.
"for i in range(1)" - HUST! Kein Kommentar. :oops:
Ich denke, in dem try/except-Block sollte, wenn das der für das Laden der Sounddateien zuständige war, evtl. eine Runtime-Error-Ausnahme kommen. Weiß ich nicht. Muss ich mich nochmal mit beschäftigen, welche es alles gibt bzw. wie die kategorisiert sind.
Praktisch sollte ein evtl. nicht-laden der Dateien abgefangen werden, so dass das Programm notfalls auch ohne Sound fortfahren könnte. Ob mir dies logisch gelungen ist, weiß ich nicht. Laufen tut das Programm/Skript aber auch ohne die Dateien. Naja...wie gesagt, ist noch viel zu lernen! :-)
Ist so abgespeichert - in Zukunft werden Ausnahmebehandlungen konkretisiert.
"sys.exit" werde ich versuchen zu meiden und mit einem break irgendwie, irgendwo die Hauptschleife in "if name == main" zu unterbrechen, müsste eigentlich machbar sein.


@ /me: Ja, das hatte mich auch gewundert, wieso das ganze nur so halb funktionierte. Ich stimme mit Dir voll und ganz überein (s.o.) und verschiebe den ganzen Komplex "OOP" erstmal etwas nach hinten.
Ich arbeite bzw. lerne mit dem Buch "Python für Einsteiger" von Thomas Theis (Galileo Comp.). Eigentlich ein, wie ich finde, sehr einfach erklärendes Buch. Leider ist - mMn - der Teil über die OOP zu kurz gekommen...aber gut, das Buch soll ja auch nur die Grundzüge der OOP / Python allg. darlegen. Für weitergehende Literatur gibts sicher noch weitere Bücher.
Wie gesagt, ist das Thema OOP bei mir nun erstmal nach hinten gerückt.
Als erstes möchte ich mein kleines Spielchen zu einem (vorläufigen...) Ende bringen, sprich: es soll (soweit...) sauber programmiert sein und funktionieren, dafür braucht es tatsächlich keine Klasse und ihre Instanzen, über einfache Funktionen lief es vorher auch wunderbar und ist unkomplizierter und für mich mit Sicherheit sauberer zu programmieren.
Darauf wird also erstmal mein Hauptaugenmerk liegen.


@ Sirius3: Danke für deine Hinweise! Ich habe mich gestern Abend schonmal drangesetzt und die reading()-Funktion umgearbeitet und deine Tipps umgesetzt.
Im letzten Teil entscheidet sich nun, ob die Ausgabe der nächsten Zeile 0.1 Sekunden oder 1.6 Sekunden lang auf sich warten lässt. Jede Code-Zeile kommt folglich nur noch einmal vor und die txt-Datei öffne ich gleich direkt mit "with open" und, soweit ich das nun mal zu behaupten wagen kann, "iteriere ich auch gleich über das Objekt"...*hust* (falls man das so sagt? Die Zeilen werden dennoch gesplittet, vielleicht habe ich da also auch was falsch verstanden...ich schicke dann alles nochmal gemeinsam hoch)
Das mit dem unleserlichen Code kann ich noch nachvollziehen, zu komplex finde ich den jedoch nicht. Liegt allerdings wahrscheinlich daran, dass ich ihn selber geschrieben habe und mir andere Codes viel komplexer vorkommen.
Dennoch nehme ich deinen Hinweis sehr gerne an und werde versuchen, den Code kürzer zu gestalten bzw. mit " ``` " statt mit " \ " zu arbeiten, sofern das nötig werden sollte.
Bei der Funktion "bisection()" habe ich gestern Abend schon die Variablen "obergrenze" / "untergrenze" in "right" / "left" umgeändert, da der Code so nun auch in eine Zeile passt.


@ HarteWare: Danke für den Link !! Sowas habe ich gesucht! Irgendwie habe ich bisher nur komisch abstrakte Abhandlungen & Meinungen oder - für mich - ziemlich komische Beispiele zur OOP und Klassen gefunden. Da wird das alles recht anschaulich erklärt - TOP !
Ich hab einfach ab Kapitel 3 oder 4 (?) kurz angefangen reinzulesen, und bis Kapitel 8 auch alles verstanden. Tolle Sache auch mit den DocStrings - die hab gestern Abend gleich in reading() und bisection() eingebaut - bisher fand ich alles Klasse erklärt!


Allgemein vielleicht noch kurz erwähnt: Ich hab mir die NINJA-IDE installiert.
Ich finde geany zwar übersichtlicher, und irgendwie wohl auch "leichter" / schneller, finde aber gut, dass der mir die ganzen Fehler gleich mit ausgibt, ebenso wie die PEP8-Hinweise. Über manches hab ich mich zwar auch gewundert, z.B. dass es meint, ich solle div. Formeln statt in "a = range(int(b, b-a))" folgendermaßen "a = list(range(int(a, b-a)))" schreiben, weil der Code vorher auch funktioniert hat, aber es scheint zu funktionieren.
Ich finde, dass ganze ist jedenfalls eine gute Unterstützung, um den Code gleich von Anfang an "etwas richtiger" zu gestalten.


So. Das wars dann auch erstmal von mir ;-)

Grüße
BSA
Oftmals beschleicht mich hier im Forum das heimliche Gefühl, an verschiedenen Stellen mal ein einfaches "Bahnhof" zu posten.

Wann du den Fisch auch fängst, er ist frisch. Sprichwort
BlackJack

@BSA: Ich kenne Ninja-IDE nur vom Namen. Bei dem Hinweis mit dem zusätzlichen `list()` solltest Du eventuell mal nachforschen *warum* Dir der gegeben wird. Das klingt nach einem Hinweis um Python 2 Quelltext nach Python 3 zu portieren. Falls Du schon Python 3 verwendest macht das keinen Sinn, ansonsten könnte man an der Stelle `xrange()` statt `range()` verwenden wenn es auch ohne das `list()` funktioniert.

Und man muss immer im Hinterkopf behalten, dass manchmal auch falsche Hinweise kommen wenn die Prüfung entweder etwas nicht richtig interpretieren konnte, oder etwas falsch interpretiert. Wenn die Ninja-IDE zum Beispiel Pylinter integriert bekommt man bei so etwas hier Hinweise auf nicht konforme Namen bei `Point` und `get_first`, ganz einfach weil nicht erkannt wird dass es sich um einen Datentyp und eine Funktion handelt, wofür die Namen jeweils den Konventionen entsprechen:

Code: Alles auswählen

from collections import namedtuple
from functools import partial
from operator import itemgetter

Point = namedtuple('Point', 'x y')
get_first = partial(itemgetter, 0)
Man darf also nicht blind jedem Hinweis folgen. Sollte aber über alle nachdenken. :-)
BSA
User
Beiträge: 38
Registriert: Freitag 6. Dezember 2013, 07:49

Kann gut sein! Ich bin zwar grad an einem andern Rechner, werd mir das aber zuhause noch mal genauer anschauen. Danke für den Hinweis!
Ich hatte auch irgendetwas von Py2to3 gelesen, wusste nur nicht, dass die Funktion (anscheinend...) "an" ist. Hatte sie in den Präferenzen eigentlich auch aus logischen Gründen nicht extra eingeschaltet...
Das mit Pylinter und den drei Funktionen aus den jeweils drei Modulen hab ich jetzt zwar ehrlich gesagt nicht verstanden, und auch sagen mir die Module alle nichts, aber auf GitHub hab ich kurz was mit Sublime2/3-Text bzgl. Pylinter gelesen. Die andern drei werd ich mir mal bei Zeiten auch noch anschauen, wozu die da sind.

Ich werd das list() also nachher wieder ausbauen. Und in Zukunft versuchen darauf zu achten, warum Ninja mir dies oder jenes eigentlich genau vorschlägt... :-D

Grüße
BSA
Oftmals beschleicht mich hier im Forum das heimliche Gefühl, an verschiedenen Stellen mal ein einfaches "Bahnhof" zu posten.

Wann du den Fisch auch fängst, er ist frisch. Sprichwort
BlackJack

@BSA: Pylinter ist ein Programm welches Python-Quelltext statisch analysiert und Warnungen generiert wenn gegen Konventionen verstossen wird, bei Fehlern die es erkennt und auch bei einiges Sachen die zumindest komisch sind. Zum Beispiel wenn man ein Funktionsargument innerhalb einer Funktion nicht verwendet, oder wenn man einem lokalen Namen etwas zuweist und den dann nicht verwendet. Das wird von den vielen IDEs für Python unterstützt, beziehungsweise verwendet um so etwas im Editor dann anzuzeigen. Kann man auch als alleinstehendes Programm benutzen. Für Sublime Text gibt es ein Plugin das jedes mal beim Speichern vom Quelltext eine Prüfung laufen lässt.

Der Punkt bei dem Beispielquelltext ist, dass `namedtuple()` eine Klasse als Ergebnis liefert und `partial()` eine Funktion. Das bekommt Pylinter aber nicht mit und meckert, dass die Namen `Point` und `get_first` nicht der Konvention für Konstanten entsprechen, weil die halt nicht mit ``class`` und ``def`` zustande gekommen sind.

Edit: Wobei mir gerade auffällt das `get_first` falsch definiert ist, das müsste nur ``get_first = itemgetter(0)`` heissen. Und für `itemgetter()` gilt aber was ich für `partial()` gesagt habe: das liefert als Ergebnis eine Funktion.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@NoPy:
Ich versuche mal, mit einem zugebenermaßen skurrilen Bsp. das WARUM zu beleuchten:

Ein Bauer kommt zu Dir und sagt: "Ich will meine Kühe zählen." Das WAS ist scheinbar schnell erfasst - Kühe zählen oder formaler, gesucht ist die Anzahl seiner Kühe. Daraus folgt die Frage nach dem WIE.

Du sagst: "Zähl doch einfach durch" - "nee, geht nicht sind zu viele" - "Dann mach doch ne Strichliste" - "Ja kann ich machen, aber die laufen immer kreuz und quer, da zähl ich einige mehrfach" - "Dann bind sie vorher an" - "Auf der Weide?"

Die Lösungswege oder Prozeduren (WIE) waren bisher wenig fruchtbar, da Information über das WAS vorenthalten wurde. "Ok verstehe, dann miete Dir einen Helikopter und fotografiere die Herde von oben, dann kannst Du sie auszählen" - "Ja und Nachbars Kühe?" - "Nachbars Kühe?" - "Na die sind doch in meine Weide eingebrochen" - "Ehm Kommando Pimperle, WARUM willst Du Deine Kühe zählen?"

Grundproblem ist die lückenhafte Problembeschreibung (WAS), welche nicht als Lösung taugt. Ein Problem, mit dem jeder Programmierer im Umgang mit Kundenwünschen ständig konfrontiert wird. Die Frage nach dem WARUM nötigt dem Problemsteller den Sinn oder zumindest die Hintergründe ab, mit deren Wissen die Übersetzung in eine andere Domäne einfacher gelingt, da man relativ schnell die Freiheitsgrade und etwaige Einschränkungen erkennt (semantische Erfassung). Nicht selten stellt sich dann auch das Problem anders dar.
BSA
User
Beiträge: 38
Registriert: Freitag 6. Dezember 2013, 07:49

Moin,

@ BlackJack: Stimmt, es wurde mir sogar mal hier im Forum zum Testen/Ausgeben phys. Zeilen empfohlen, ich war da nur nicht durchgestiegen und hatte es daher zurückgestellt :-)

Ich habe jetzt gestern Abend noch den ganzen Code um- bzw. restrukturiert, suche allerdings noch einen Lösungsweg, lokale Variablen, welche in Bspw. Funktion1() erstellt werden, an Funktion2() zu übergeben, ohne dass Funktion1() dabei Funktion 2(Variable) aufrufen muss, um den Code so wenig rekursiv wie möglich zu gestalten...ist gar nicht so einfach.
Mit `return` klappt es anscheinend nicht, da die Variable nun zwar immerhin nicht mehr im globalen Namensraum gesucht wird, Funktion2() aber dennoch nicht weiß, dass sie die Variable aus Funktion1() übergeben bekommen soll / Funktion1() es nicht schafft, die Variable aus dem Mainloop heraus an Funktion2() zu übergeben.

In einer früheren Version (ohne Klassen, eben wie jetzt, mit weniger Funktionen jedoch) habe ich die Variablen fälschlicherweise durch rekursive Aufrufe aus den Funktionen heraus übergeben. Ich suche jetzt die Möglichkeit, diese über den Mainloop heraus jeweils von Funktion1 -> Mainloop -> Funktion2 -> Mainloop -> Funktion3 ... zu übergeben, ohne die Variablen im globalen Namensraum deklrarieren zu müssen...
Wahrscheinlich hab ich irgendwo einfach 'nen Denkfehler...
Ich probier mich da jetzt aber nochmal kurz dran. Und wenn mir die Lösung nicht wie Schuppen von den Augen fallen sollte, frag ich wohl heute Abend nochmal nach...
Oftmals beschleicht mich hier im Forum das heimliche Gefühl, an verschiedenen Stellen mal ein einfaches "Bahnhof" zu posten.

Wann du den Fisch auch fängst, er ist frisch. Sprichwort
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

BSA hat geschrieben:Ich suche jetzt die Möglichkeit, diese über den Mainloop heraus jeweils von Funktion1 -> Mainloop -> Funktion2 -> Mainloop -> Funktion3 ... zu übergeben, ohne die Variablen im globalen Namensraum deklrarieren zu müssen...
Wahrscheinlich hab ich irgendwo einfach 'nen Denkfehler...

Code: Alles auswählen

def main():
    # kompakt ganz einfach so (und wenn es lesbar bleibt)
    func1(func2(func3()))
    #braucht man einen Wert mehrfach, gerne auch so:
    value = func1()
    func2(value)
    func3(value)
:K
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BSA
User
Beiträge: 38
Registriert: Freitag 6. Dezember 2013, 07:49

Na, da wär ich aber von alleine erstmal wohl kaum draufgekommen...
Ich weiß zwar noch nicht so ganz, wie ich das ganze in meinem 400+xx-Zeilen-Code umsetzen soll, werd mich aber nachher mal dran probieren!

Das Prinzip jedenfalls hab ich mal eben kurz ausprobiert und bei rausgekommen ist folgendes:

Code: Alles auswählen

#!/usr/bin/env python3

def multiplikation():
	a = int(input(' a = '))
	b = int(input(' b = '))
	produkt = a * b
	print('Das Produkt von {} x {} ist gleich: {}'.format(a,b,produkt))
	return produkt

def summe():
	a = int(input(' a = '))
	b = int(input(' b = '))
	summ_e = a + b
	print('Die Summe von {} und {} ist gleich: {}'.format(a,b,summ_e))
	return summ_e

def subtraktion():
	a = int(input(' a = '))
	b = int(input(' b = '))
	while True:
		if a > b:
			differenz = a - b
			print('Die Differenz von {} zu {} ist: {}'.format(a,b,differenz))
			break
		else:
			differenz = b - a
			print('Die Differenz von {} zu {} ist: {}'.format(b,a,differenz))
			break
	return differenz

def division():
	a = int(input(' a = '))
	b = int(input(' b = '))
	while True:
		if a > b:
			quotient = a / b
			print('Der Quotient aus {} / {} ist = {}'.format(a,b,quotient))
			break
		else:
			quotient = b / a
			print('Der Quotient aus {} / {} ist = {}'.format(b,a,quotient))
			break
	return quotient

def quadrat():
	a = int(input(' a = '))
	b = int(input(' b = '))
	sqr1 = a * a
	sqr2 = b * b
	print('Das Quadrat von {} ist gleich: {}'.format(a,sqr1))
	print('Das Quadrat von {} ist gleich: {}'.format(b,sqr2))
	return sqr1, sqr2

def potenz():
	a = int(input(' a = '))
	b = int(input(' b = '))
	poten_z = a ** b
	print('Die Potenz von {} und {} ist gleich: {}'.format(a,b,poten_z))
	return poten_z

def ergebnisse():
	while True:
		v1 = summe()
		v2 = subtraktion()
		v3 = multiplikation()
		v4 = division()
		v5_1 = quadrat()
		v5_2 = quadrat()
		v6 = potenz()
		print('''Die Ergebnisse sind :
		1. Summe          : {}
		2. Subtraktion    : {}
		3. Multiplikation : {}
		4. Division       : {}
		5. Quadrate       : Q1 {}    Q2 {}
		6. Potenz         : {}
		--- Ende der Ergebnisliste'''.format(v1,v2,v3,v4,v5_1,v5_2,v6))


if __name__ == '__main__':
	ergebnisse()
Das sieht auch so aus als wenn es funktionieren würde.
Ich hab versucht nach deiner zweiten Methode vorzugehen, und den Wert der benötigten Variable durch Ausführen der jeweiligen Funktion über eine return-Anweisung an eben diese zu binden.
Das ganze geschieht hier in der Funktion ergebnisse() - sollte aber im Grunde auch mit etlichen if/elif/else-Abfragen in einem (für mich...) "etwas komplexeren Skript" funktionieren... ich werds ausprobieren!

Ich hoffe nur, dass es auch genausogut in meinem kleinen Spielchen klappt.
Das Problem seh ich nämlich darin, dass ich nicht für jede benötigte Variable jedes mal erneut die jeweilige Funktion durchlaufen lassen kann, da der Spieler evtl. einfach nur nochmal wiederholen möchte...
Allerdings fällt mir da auch grad auf, dass die Werte der dann ja erneut, jedoch nur noch lesend benötigten Variablen in dem mainloop noch weiterhin gespeichert sein dürften, bis sie eben durch erneuten Aufruf der Funktion neu gebunden werden...hmm...es bleibt spannend! :-D

Wenn der Wert aller nach erstmaligem Durchlauf erstellten Variablen bis zum erneuten Überschreiben der Variablen durch erneuten Funktionsaufruf durch Eingabe des Nutzers lokal in der letzten while-Schleife innerhalb der main()-Funktion gespeichert bleibt, und solange mit ihrem jeweiligen Wert weiterhin von jeder noch zu nutzenden Funktion gelesen werden kann, dann müsste es theoretisch funktionieren. Und rekursiv sollte es mMn dann eigentlich auch nicht mehr sein, da jede benötigte Funktion jeweils nur durch die Hauptfunktion, dem mainloop, aufgerufen würde und die ganzen andern Funktionen sich selber nicht mehr berühren/aufrufen würden.

Wenn das also klappt, bin ich ein ganzes gutes Stück weiter, als ich noch jetzt bin.

In der Theorie klingt das auch sehr einfach. Was für eine Tipperei das nachher aber noch wird, bleibt gespannt abzuwarten ;-)

Danke nochmal für den Hinweis!

Grüße
BSA


edit: unnötigen Code rausgeschmissen (a = int(input(...)) -> a = input(...)
Bei den for-Schleifen bekomme ich keinen einmaligen Durchlauf durch "for i in 1" hin, int sei nicht iterierbar...daher durch while-Schleifen ersetzt!
Zuletzt geändert von Anonymous am Dienstag 7. Januar 2014, 19:36, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
Oftmals beschleicht mich hier im Forum das heimliche Gefühl, an verschiedenen Stellen mal ein einfaches "Bahnhof" zu posten.

Wann du den Fisch auch fängst, er ist frisch. Sprichwort
BlackJack

@BSA: Mit sinnfreien Schleifen hast Du's irgendwie. Die in `subtraktion()` und `division()` werden grundsätzlich genau *einmal* durchlaufen. Und wenn man nicht zumindest potentiell etwas wiederholen will, braucht man keine Schleife.

Das Ergebnis jeweils aus- *und* zurückzugeben ist irgendwie redundant.

Allen Rechenfunktionen ist gemeinsam, dass sie `a` und `b` vom Benutzer erfragen. Das könnte man also in eine Funktion heraus ziehen. So wirklich unterscheiden tun sie sich aber nur durch die Rechnung und den Ausgabetext. Also könnte man eine generische Funktion für eine binäre Rechenoperation schreiben und die eigentliche Rechenfunktion und den Text als Argumente herausziehen. Zumindest zwei der Rechenfunktionen kann man direkt aus dem `operator`-Modul nehmen. Eigentlich auch bei `subtraktion()` und `division()`, denn die Fallunterscheidung dort verstehe ich nicht so ganz. Warum?

Und warum berechnet Quadrat zwei Quadrate und nicht nur eines?

Statt der durchnummerierten `v`\s in `ergebnisse()` hätte man eine Liste verwenden können.

Der Funktionsname passt nicht zu einer Funktion eher zu Werten — eben Ergebnisse.

Und natürlich kann man nicht über eine 1 iterieren. Was sollte denn da das Ergebnis in jedem Schleifendurchlauf sein?
BlackJack

Mal spasseshalber eine allgemeine Funktion für das ausrechnen einer n-nären Operation (n≤26) herausgezogen und damit dann die ganzen Operationen definiert:

Code: Alles auswählen

from __future__ import print_function
from functools import partial
from itertools import islice
from operator import add, mul, pow as pow_, sub, truediv
from string import ascii_lowercase

try:
    input = raw_input
except NameError:
    pass  # We are on Python 3.


def do_n_ary_function(arity, function, text):
    if arity > len(ascii_lowercase):
        raise ValueError(
            'max {} arguments allowed for function'.format(len(ascii_lowercase))
        )
    arguments = [
        int(input(' {} = '.format(var_name)))
        for var_name in islice(ascii_lowercase, arity)
    ]
    result = function(*arguments)
    print(text.format(*arguments, result=result))


multiplicate = partial(
    do_n_ary_function, 2, mul, 'Das Produkt von {} x {} ist gleich: {result}'
)
sum_ = partial(
    do_n_ary_function, 2, add, 'Die Summe von {} und {} ist gleich: {result}'
)
subtract = partial(
    do_n_ary_function, 2, sub, 'Die Differenz von {} zu {} ist: {result}'
)
divide = partial(
    do_n_ary_function, 2, truediv, 'Der Quotient aus {} / {} ist = {result}'
)
square = partial(
    do_n_ary_function,
    1,
    lambda x: x**2,
    'Das Quadrat von {} ist gleich: {result}'
)
power = partial(
    do_n_ary_function, 2, pow_, 'Die Potenz von {} und {} ist gleich: {result}'
)


def main():
    while True:
        for operation in [sum_, subtract, multiplicate, divide, square, power]:
            operation()
        print()


if __name__ == '__main__':
    main()
BSA
User
Beiträge: 38
Registriert: Freitag 6. Dezember 2013, 07:49

Moin.

Ja, das kann sein. Im Nachhinein fällt mir auch auf, dass die Schleife total unnötig ist. Eine einfach if/else hätte wohl gereicht...
Ich werde _versuchen_ in Zukunft etwas mehr darauf zu achten.
Ich muss jedoch dazu sagen, dass ich das ganze nur als Test-Skript geschrieben habe, um die Funktionsweise aus Hyperion's Antwort zu prüfen/verstehen/anzuwenden. Ich hatte da leider keinen Zugriff auf mein eigenes kleines Projekt, bzw. nur auf recht alte Versionen - daher musste ich improvisieren ;-)

Zur 'return'-Anweisung: Ich war eigentlich davon ausgegangen, dass erst so das Ergebnis aus der Funktion an die funktionsaufrufende Variable zurückgegeben wird. Ist das denn nicht so? Das muss ich nachher mal ausprobieren. War bisher davon ausgegangen, dass erst die 'return'-Anweisung den Wert zurückgibt... :K

Das mit einer extra input()-Funktion hatte ich mir ursprünglich auch überlegt, da ich das ganze aber recht fix eintippen musste/wollte, habe ich da evtl. nicht alles umgesetzt, was mir dazu eingefallen wäre.

Das mit der doppelten Berechnung in quadrat() kann ich grad nicht mehr erklären. Ich hab jedoch recht planlos angefangen, was sich am Ergebnis wohl auch ablesen lässt... :oops:

Deinen Code finde ich interessant. Ich werde mich damit die Tage mal beschäftigen, besonders mit den Modulen !!

Zu meinem ursprünglichen Code: Ich habe jetzt alles soweit, dass es läuft. Jedoch bin ich noch dabei, manche Fehler (solche, die mir auffallen...) auszubessern und evtl. unbenötigte Variablen rauszunehmen, sofern sie über den Schleifenablauf sowieso umgesetzt würden, sprich: Wo der Kontrollfluß in meinem Code schon das ein oder andere regelt, bedarf es evtl. der einen oder anderen durch die Funktion gesetzte Variable nicht mehr. Da bin ich noch am rumprobieren...

Die Länge der physikalischen Zeilen hat sich jedoch kaum merklich geändert, dafür gibt es allerdings auch keine Klasse mehr und eine mainloop() kümmert sich um (fast) alle anderen Funktionsaufrufe...außerdem gibt es die geforderten DocStrings und eine neue kleine (Steuerungs-)Funktion, die mainloop()...mal schauen, zufrieden bin ich wie gesagt selber noch nicht damit !
Veröffentlichen werde ich sie wahrscheinlich morgen oder übermorgen - je nachdem wieviel Zeit ich bis dahin noch über habe.

Viele Grüße
BSA
Oftmals beschleicht mich hier im Forum das heimliche Gefühl, an verschiedenen Stellen mal ein einfaches "Bahnhof" zu posten.

Wann du den Fisch auch fängst, er ist frisch. Sprichwort
BlackJack

@BSA: Das mit ``return`` hast Du schon richtig verstanden. Es ist halt ungewöhnlich das eine Funktion das Ergebnis dem Benutzer ausgibt *und* dann noch zum Aufrufer zurück gibt. Man macht normalerweise entweder das eine oder das andere. In der Regel eher zurückgeben, denn wenn man Berechnung und Ausgabe trennt, kann man die Funktion flexibler verwenden, zum Beispiel sowohl in einem Kommandozeilenprogramm als auch in einer GUI. Oder in einer Webanwendung, oder…
BSA
User
Beiträge: 38
Registriert: Freitag 6. Dezember 2013, 07:49

Moin BlackJack,

klingt logisch. Berechnen in Bspw. Func1(), Func2() etc., zurückgeben an (bspw.) Ausgabe() und dort dann erstmalig ausgeben und evtl. auch speichern, bzw. wenn man über eine main() arbeiten sollte:
-- main() [ruft auf] a=func1(), b=func2() ... [main() [erhält Werte a / b zurück]
-> main() [ruft auf] (bspw.) output() / work_with / write_sequential() ... -> die übergebenen Werte sind weitergereicht und werden "dort" weitergenutzt

Gestern Abend ist bei meinem Spiel noch eine weitere Funktion hinzugekommen, außerdem ist eine weitere Variable rausgeflogen, die anscheinend keine wichtige Funktion hatte (while-Schleife und if-Abfrage mit einer anderen Variable tun das gleiche)

Jetzt habe ich das Problem, dass ich überhaupt keine globalen Werte mehr habe, was vorher noch anders war.
Das führt bei mir zu einem Problem mit der Sound-Ausgabe, da ich nicht jede Sounddatei als Variable immer manuell hin- und herreichen möchte, insbesondere da es ja immer mal sein kann, dass noch Sounddateien dazukommen bzw. verändert werden sollen.
Daher überlege ich mir an dieser Stelle doch wieder tatsächlich eine Klasse Sound zu erstellen.
Das wird aber wohl eine _besonders einfache_ Klasse werden, da nur eine Methode "play" benötigt wird. Mit der __init__ müsste ich mich allerdings nochmal beschäftigen, da dort ja die Sounddateien bzw. die File-Attribute initiiert (definiert) werden müssten.

Wie schon zuvor einmal geschrieben:

Code: Alles auswählen

from fun.local import stress, hammer

tastatur = True

def symbiose():
  if fun == stress:
    print('Es bleibt spannend...')
  elif fun > stress:
    print('Das ist aber toll!')
  else:
    tastatur.hammer.go()
;-)
Oftmals beschleicht mich hier im Forum das heimliche Gefühl, an verschiedenen Stellen mal ein einfaches "Bahnhof" zu posten.

Wann du den Fisch auch fängst, er ist frisch. Sprichwort
Antworten