Frage bezüglich if-statement Verschachtelung (PEP8)

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.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Ja, allein schon weil sich der Name nicht an PEP 8 hält ;-)
Das Leben ist wie ein Tennisball.
Benutzeravatar
CrisBee
User
Beiträge: 61
Registriert: Mittwoch 2. Oktober 2013, 10:45
Wohnort: Bielefeld
Kontaktdaten:

*hand hinhalt*

Gerade nochmal PEP8 nachgeschlagen und wie folgt geändert: def get_arguments():
Das Reallife ist nur etwas für Leute, die keine Freunde im Internet haben! :P
Meine Fotografie: http://www.cutefeet.de
Benutzeravatar
CrisBee
User
Beiträge: 61
Registriert: Mittwoch 2. Oktober 2013, 10:45
Wohnort: Bielefeld
Kontaktdaten:

Ich muss jetzt leider doppelt Posten, sorry!

Es ist zum Verzweifeln. Seit gestern sitze ich wie blöd vor dem Code und bekomme es EINFACH nicht gebacken. Ich bin am Googlen, Lesen, Ausprobieren, etc...es will einfach nicht.

Ich bin soweit, dass argparse funktioniert, bis dahin war es auch nicht so schwer. Allerdings bekomme ich es einfach nicht geschi**sen, dass ich die zwei übergebenen Zahlen "filter", um damit zu rechnen. Mir fehlt jeglicher Ansatz... -.-

Code: Alles auswählen

#!/usr/bin/env python
 
import argparse
import operator

def get_arguments():
    parser = argparse.ArgumentParser()
    parser.add_argument("-a", "--add", nargs=2, help="Add two numbers")
    parser.add_argument("-s", "--sub", nargs=2, help="Subtract two numbers")
    parser.add_argument("-m", "--mul", nargs=2, help="Multiplicate two numbers")
    parser.add_argument("-d", "--div", nargs=2, help="Divide two numbers")
    args = parser.parse_args() 
    return args
        
def main():
    '''Der return Wert von get_arguments() wird in args gespeichert'''
    args = vars(get_arguments())
    '''Hier schaffe ich es, zumindest die Values auszulesen.
    Je nachdem welches Argument verwendet wird - -a oder -s - gibt er dann die Values aus.'''
    print args['add']
    print args['sub']
    
    
    operators = {"add": operator.add, "sub": operator.sub, "mul": operator.mul, "div": operator.div}  
    
    '''Hier ein Test, ob der Aufruf der operator im Dict klappt.'''
    a=5
    b=12 
    print operators['add'](a, b)  
    print operators['sub'](a, b)
    print operators['mul'](a, b)
    print operators['div'](a, b)
    
if __name__ == "__main__":
    main()
Mal davon abgesehen, dass der meiste Code wahrscheinlich wieder nicht da ist, wo er sein sollte (ich habe es zum Testen aber in die main gepackt):

Wie komme ich an die blöden Werte, die dem Script übergeben werden? Ich bin schon wieder kurz davor alles zu schmeißen, weil ich mir wie der letzte Vollidiot vorkomme. Bin ich wirklich zu dumm für die Programmierung?

Ich glaube ich sehe den Wald vor lauter Bäumen schon nicht mehr.

*HILFE in den Sand kratz*

EDIT: Code geändert
Das Reallife ist nur etwas für Leute, die keine Freunde im Internet haben! :P
Meine Fotografie: http://www.cutefeet.de
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo.

Als erstes fällt auf, dass du die Parameter nicht so verwendest, wie sie verwendet werden sollten. "--xy" ist ein Indikator dafür, dass der Parameter optional sein soll. Du hast also lauter optionale Operationen, welche auch noch alle gleichzeitig aufgerufen werden können.

Ein weiterer wichtiger Punkt: Strings sind keine Kommetare. Wenn du mehrzeilige Kommentare haben willst, dann schreibe einfach für jede Zeile ein # ;-)

Da das Dictionary mit den Operatoren konstant ist, sollte es auch nach außen gezogen werden.

Zeilen 12 und 13 kannst du wieder zusammenfassen.

Das ganze sieht dann so aus:

Code: Alles auswählen

import argparse
import operator

OPERATORS = {
    "add": operator.add,
    "sub": operator.sub,
    "mul": operator.mul,
    "div": operator.div} 


def get_arguments():
    parser = argparse.ArgumentParser()
    parser.add_argument("operator", choices=OPERATORS.keys())
    parser.add_argument("op1", type=int)
    parser.add_argument("op2", type=int)
    
    return parser.parse_args()


def main():
    args = get_arguments()
   
    print OPERATORS[args.operator](args.op1, args.op2)
   
if __name__ == "__main__":
    main()
und du kannst es mittels

Code: Alles auswählen

prog.py add 1 2
aufrufen.
Das Leben ist wie ein Tennisball.
Benutzeravatar
CrisBee
User
Beiträge: 61
Registriert: Mittwoch 2. Oktober 2013, 10:45
Wohnort: Bielefeld
Kontaktdaten:

*an die Stirn klatsch...*

So einfach...soooo einfach...und ich Schnulli bekomme das natürlich wieder nicht hin. Und jetzt wo ich es lese, wie du es gelöst hast ergibt es alles einen Sinn für mich. Danke dir!

Zu den Kommentaren mag ich noch was sagen. Ich habe bisher üblicherweise immer die Kommentare mit der Raute geschrieben. Ich weiß nicht, wieso ich jetzt auf den Trichter kam, mehrzeilige Kommentare mit den 3-fachen Singlequotes zu beginnen und zu beenden. Wahrscheinlich habe ich mir das wieder irgendwo falsch abgeschaut. Danke auch dafür nochmal! :)
Das Reallife ist nur etwas für Leute, die keine Freunde im Internet haben! :P
Meine Fotografie: http://www.cutefeet.de
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Wahrscheinlich hast du die Triplequotes irgendwo als Docstrings gesehen und im Eifer des Gefechts den Einsatzzweck etwas zu weit extrapoliert. Oder es lag wieder am Wetter :D
Das Leben ist wie ein Tennisball.
Benutzeravatar
CrisBee
User
Beiträge: 61
Registriert: Mittwoch 2. Oktober 2013, 10:45
Wohnort: Bielefeld
Kontaktdaten:

Es MUSS einfach das Wetter gewesen sein! :D Wobei hier in Bielefeld, zumindest an meinem Fleckchen, der Regen Einzug gefunden hat und auch Blitze zuckten vereinzelt übers Firmament. Abkühlung -> Gegeben!

Was haltet ihr von dem Vorschlag, dass man den Thread umbenennt und mit einem [Gelöst] vermerkt? Werde dann schauen den Code noch in eine schöne Form zu bringen und RICHTIG zu kommentieren und dann hat man was, worauf man verweisen kann. Ist nur eine Idee! :)
Das Reallife ist nur etwas für Leute, die keine Freunde im Internet haben! :P
Meine Fotografie: http://www.cutefeet.de
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Threads werden hier nicht als gelöst markiert. Es soll niemand davon abgehalten werden bereits gelöste aufgaben noch weiter zu verbessern oder zu kommentieren.

Den Code in eine saubere Form bringen finde ich aber eine gute Idee. Da diese Frage in ähnlicher Form häufiger vorkommt, gäbe es eine schöne Musterlösung dazu. Die Thema hat Hyperion gestern schon angemerkt. Vielleicht wäre das fertige Resultat auch etwas fürs Wiki.

Und als Bonusaufgabe: Wie lassen sich nicht-binäre Operationen umsetzen? ;-)
Das Leben ist wie ein Tennisball.
Benutzeravatar
CrisBee
User
Beiträge: 61
Registriert: Mittwoch 2. Oktober 2013, 10:45
Wohnort: Bielefeld
Kontaktdaten:

Achso, verstehe! :)

Genau, Hyperion sprach es gestern an, deshalb wollte ich es nochmal aufgreifen. Wie der Code jetzt steht, ist das so in Ordnung? Ist der Code gut getrennt? Gehört die Ausgabe in die main?
Fällt mir gerade schwer so ein kurzes Stück Code vernünftig zu kommentieren! :D

EDIT: Was meinst du mit nicht binär? Also mehr als nur 2 Operanden und mehrere Operatoren?

EDIT 2: Habe den Code jetzt angepasst und mühselig mit wahrscheinlich total sinnlosen Kommentaren versehen! XD

Code: Alles auswählen

#!/usr/bin/env python

import argparse
import operator

#dictionary with operator functions
OPERATORS = {
    "add": operator.add,
    "sub": operator.sub,
    "mul": operator.mul,
    "div": operator.div} 

def get_arguments():
    #creating an argparse object
    parser = argparse.ArgumentParser()
    #adding the arguments argparse should expect
    parser.add_argument("operator", choices=OPERATORS.keys())
    parser.add_argument("op1", type=int)
    parser.add_argument("op2", type=int)
    
    #actually give back what the parser gets
    return parser.parse_args() 
    
def calculate():
    #put in args what get_arguments returns
    args = get_arguments()
    #return the result
    return OPERATORS[args.operator](args.op1, args.op2)

def show_result():
    #print the return value from calculate()
    print calculate()

def main():
    #call the show_result function to display the result
    show_result()
    
if __name__ == "__main__":
    main()
Ich denke ich habe es mit der Auslagerung auf so viel Teilfunktionen auch ein wenig übertrieben!? :P
Zuletzt geändert von CrisBee am Dienstag 29. Juli 2014, 20:08, insgesamt 2-mal geändert.
Das Reallife ist nur etwas für Leute, die keine Freunde im Internet haben! :P
Meine Fotografie: http://www.cutefeet.de
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

CrisBee hat geschrieben: EDIT: Was meinst du mit nicht binär? Also mehr als nur 2 Operanden und mehrere Operatoren?
Ja, hier mal an einem Clojure-Beispiel verdeutlicht:

Code: Alles auswählen

ser=> (+)
0
user=> (+ 1)
1
user=> (+ 1 2)
3
user=> (+ 1 2 42 66 999)
1110
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
CrisBee
User
Beiträge: 61
Registriert: Mittwoch 2. Oktober 2013, 10:45
Wohnort: Bielefeld
Kontaktdaten:

Achso, also ein Operator, aber diesen auf alle Operanden anwenden. Da biete sich wohl eine Iteration an!^^
Das Reallife ist nur etwas für Leute, die keine Freunde im Internet haben! :P
Meine Fotografie: http://www.cutefeet.de
BlackJack

@CrisBee: Die Funktionen sind auf jeden Fall unflexibel verkettet. So machen sie nicht das was der Name vermuten lässt. `show_result()` sollte eine Funktion sein die ein Ergebnis anzeigt. Deine Funktion wertet aber erst die Kommandozeilenargumente aus und berechnet das Ergebnis dann. Die Berechnungsfunktion berechnet nicht nur, sondern wertet vorher die Kommandozeilenargumente aus. Einzig die Funktion zur Auswertung der Kommandozeilenargumente macht tatsächlich nur genau das. Bis auf diese Funktion kann man die anderen nicht einzeln testen.

Die Kommentare sind in der Tat zu viel des guten. Kommentare sollten einen Mehrwert zum Code bieten, also etwas enthalten was man nicht schon ganz einfach am Code sehen kann. In der Regel kommentiert man eher *warum* man etwas so macht wie man es im Code macht, und nicht *was* der Code macht. Das sollte aus dem Code selbst ersichtlich sein.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

CrisBee hat geschrieben:Achso, also ein Operator, aber diesen auf alle Operanden anwenden. Da biete sich wohl eine Iteration an!^^
Das greift noch nicht weit genug. Wiederholte Anwendung eines ist nur ein Sonderfall. Ein unärer Operator nimmt einen Operanden entgegen, zum Beispiel "cos", "sin", "tan", etc. Ein binärer Operator nimmt zwei Operanden entgegen, wie Addition, Subtraktion, etc. Ternäre Operatoren drei Operanden und n-äre Operatoren haben n Operanden. Letzteres bedeutet aber nicht, dass die selbe Operation immer und immer wieder angewendet wird. Du könntest dir zum Beispiel selber einen Operator definieren:

Code: Alles auswählen

def poly(d, c, b, a):
    return d*x**3 + c*x**2 + b*x + d
Das Leben ist wie ein Tennisball.
Benutzeravatar
CrisBee
User
Beiträge: 61
Registriert: Mittwoch 2. Oktober 2013, 10:45
Wohnort: Bielefeld
Kontaktdaten:

Danke BlackJack, klingt einleuchtend wie du es sagst.
Bin jetzt leider nicht mehr am PC, werde es morgen überarbeiten und nochmal posten.

@EyDu Das werde ich mir morgen auch nochmal genauer anschauen. Für heute ist das zu hoch für mich! XD

Ich wünsche euch eine angenehme Nacht! =)
Das Reallife ist nur etwas für Leute, die keine Freunde im Internet haben! :P
Meine Fotografie: http://www.cutefeet.de
Benutzeravatar
CrisBee
User
Beiträge: 61
Registriert: Mittwoch 2. Oktober 2013, 10:45
Wohnort: Bielefeld
Kontaktdaten:

Guten Morgen liebe Pythonianer! :D

Habe gedit direkt angeschmissen und den Code nochmal verändert. Meinungen?

Code: Alles auswählen

#!/usr/bin/env python
 
import argparse
import operator

#Using a dictionary to avoid using to many if-statements
OPERATORS = {
    "add": operator.add,
    "sub": operator.sub,
    "mul": operator.mul,
    "div": operator.div}
 
def get_arguments():
    parser = argparse.ArgumentParser()
    parser.add_argument("operator", choices=OPERATORS.keys())
    parser.add_argument("op1", type=int)
    parser.add_argument("op2", type=int)
   
    return parser.parse_args()
 
def main():
    args = get_arguments()
    print OPERATORS[args.operator](args.op1, args.op2)
   
if __name__ == "__main__":
    main()
Das Reallife ist nur etwas für Leute, die keine Freunde im Internet haben! :P
Meine Fotografie: http://www.cutefeet.de
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Jetzt ist es "zu kurz". Nee, sieht fast gut aus... Du müsstest nur noch das Dispatching in eine Funktion packen, die man aufrufen kann. Denn ansonsten kann ich das ganze auch nur umständlich testen, indem ich wirklich die ``main``-Methode inklusive der Kommandozeilenparameter aufrufe.

Dir fehlt also ein ``def calc(operator, op1, op2)``!
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Sirius3
User
Beiträge: 18335
Registriert: Sonntag 21. Oktober 2012, 17:20

Hier das ganze nochmal für n-äre Operatoren:

Code: Alles auswählen

#!/usr/bin/env python
import argparse
import operator

#Using a dictionary to avoid using to many if-statements
OPERATORS = {
    "add": operator.add,
    "sub": operator.sub,
    "mul": operator.mul,
    "div": operator.div,
    "neg": operator.neg,
}

def get_arguments():
    parser = argparse.ArgumentParser()
    parser.add_argument("operator", choices=OPERATORS.keys())
    parser.add_argument("operands", type=int, nargs='*')
    return parser.parse_args()

def calculate(operator, operands):
    return OPERATORS[operator](*operands)

def main():
    args = get_arguments()
    print calculate(args.operator, args.operands)

if __name__ == "__main__":
    main()
Benutzeravatar
CrisBee
User
Beiträge: 61
Registriert: Mittwoch 2. Oktober 2013, 10:45
Wohnort: Bielefeld
Kontaktdaten:

Danke Sirius3, mein Code sieht jetzt so aus. Werde mal die Anpassung mit den n-ären Operanden vornehmen und das "neg" mit reinpacken! :)
Das Reallife ist nur etwas für Leute, die keine Freunde im Internet haben! :P
Meine Fotografie: http://www.cutefeet.de
Benutzeravatar
CrisBee
User
Beiträge: 61
Registriert: Mittwoch 2. Oktober 2013, 10:45
Wohnort: Bielefeld
Kontaktdaten:

Hier nochmal mein Code ohne die n-ären Operanden.

Code: Alles auswählen

#!/usr/bin/env python
 
import argparse
import operator

#Using a dictionary to avoid using too many if-statements
OPERATORS = {
    "add": operator.add,
    "sub": operator.sub,
    "mul": operator.mul,
    "div": operator.div
    }
 
def get_arguments():
    parser = argparse.ArgumentParser()
    parser.add_argument("operator", choices=OPERATORS.keys())
    parser.add_argument("op1", type=int)
    parser.add_argument("op2", type=int)
   
    return parser.parse_args()
    
def calc(operator, op1, op2):
    return OPERATORS[operator](op1, op2)
 
def main():
    args = get_arguments()
    print "The result is: " + str(calc(args.operator, args.op1, args.op2))
   
if __name__ == "__main__":
    main()
Habe deinen Code auch mal getestet Sirius. Das funktioniert so nicht. Oder habe ich was falsch gemacht und hätte noch mehr Anpassungen vornehmen müssen? Wenn ich mehr als zwei Zahlen per Kommandozeile übergebe, dann schimpft Python, dass mehr Argumente übergeben wurden, als erwartet wurden. Habe an das 'nargs' aber gedacht.
Das Reallife ist nur etwas für Leute, die keine Freunde im Internet haben! :P
Meine Fotografie: http://www.cutefeet.de
Sirius3
User
Beiträge: 18335
Registriert: Sonntag 21. Oktober 2012, 17:20

Ein binärer Operator erwartet eben zwei Werte. Wenn Du mehr angibst, meckert Python natürlich. Ein Nicht-Python-Programmierer kann mit dem Fehler wahrscheinlich wenig anfangen. Es wäre also Deine Aufgabe, daraus eine sprechendere Meldung zu machen.
Antworten