Matroids Matheplanet Forum Index
Moderiert von matph
Informatik » Programmieren » Python: zu langes if
Autor
Schule Python: zu langes if
Bekell
Aktiv Letzter Besuch: in der letzten Woche
Dabei seit: 05.09.2008
Mitteilungen: 2517
  Themenstart: 2020-08-26

Hallo Python Berater, Wie kann man so ein langes if kürzer machen. \sourceon Python \numberson if 11 in liste_laufvariable and 3 not in liste_laufvariable and 7 not in liste_laufvariable and 11 not in liste_pendant and len(liste_pendant)>0: \sourceoff findet Ihr nicht auch, meine Programme werden langsam kürzer und lesbarer. Das Programm läuft und funktioniert: \sourceon Python \numberson nr=0 nr1=0 zahl=10000 import matplotlib.pyplot as plt import numpy as np from sympy.ntheory import isprime from sympy import sieve from sympy import primepi def ermittel_primteiler(x): primteiler_liste=[] for i in range(3,x//2,2): if x%i==0 and isprime(i): primteiler_liste.append(i) return(primteiler_liste) for laufvariable in range(3,zahl//2,10): nr=nr+1 pendant=zahl-laufvariable-4 liste_laufvariable=ermittel_primteiler(laufvariable) liste_pendant=ermittel_primteiler(pendant) #if len(liste_laufvariable)==2 and len(liste_pendant)==2: if 11 in liste_laufvariable and 3 not in liste_laufvariable and 7 not in liste_laufvariable and 11 not in liste_pendant and len(liste_pendant)>0: nr1=nr1+1 print("Nr:",nr,"Nr1:",nr1,laufvariable,"+",pendant,liste_laufvariable,liste_pendant) \sourceoff


   Profil
DerEinfaeltige
Senior Letzter Besuch: in der letzten Woche
Dabei seit: 11.02.2015
Mitteilungen: 2999
  Beitrag No.1, eingetragen 2020-08-26

Zeilen können mit einem Backslash \ gebrochen werden. \sourceon Python if 11 in liste_laufvariable and \ 3 not in liste_laufvariable and \ 7 not in liste_laufvariable and \ 11 not in liste_pendant and \ len(liste_pendant)>0: \sourceoff


   Profil
Bekell
Aktiv Letzter Besuch: in der letzten Woche
Dabei seit: 05.09.2008
Mitteilungen: 2517
  Beitrag No.2, vom Themenstarter, eingetragen 2020-08-26

Danke, sowas wie: \sourceon Python \numberson 3,7,11 not in liste_laufvariable \sourceoff geht nicht, oder? Machen viele Bedingungen das if merklich langsam?


   Profil
DerEinfaeltige
Senior Letzter Besuch: in der letzten Woche
Dabei seit: 11.02.2015
Mitteilungen: 2999
  Beitrag No.3, eingetragen 2020-08-26

Mit "any" und "all" kann man sowas eleganter formulieren. Die Effizienz von if mit mehreren durch or/and verknüpften Bedingungen hängt von der Reihenfolge der Bedingungen ab. Genaueres steht in jedem guten Einsteigerbuch zur Programmierung.


   Profil
Bekell
Aktiv Letzter Besuch: in der letzten Woche
Dabei seit: 05.09.2008
Mitteilungen: 2517
  Beitrag No.4, vom Themenstarter, eingetragen 2020-08-26

Hallo Einfältiger, ich hab ein teures Buch zu Python. (Johannes Ernesto, Peter Kaiser Python 3) Da steht zu any und all genau 6 bzw. 7 Zeilen. Das ist mehr als wenig. Könntest Du mal mein if eleganter zusammenfassen mit all und any?


   Profil
Scynja
Aktiv Letzter Besuch: in der letzten Woche
Dabei seit: 23.02.2011
Mitteilungen: 433
Wohnort: Deutschland
  Beitrag No.5, eingetragen 2020-08-26

Allgemein kürzt man if-Bedingungen, indem man den boolschen Wert einer oder mehrerer zusammengefasster Bedingungen in eine Variable oder Funktion auslagert. Aber diese Bedingung würde ich vermutlich ganz lassen. Da steckt ja keine anspruchsvolle Logik dahinter. Bzw. die Punkte sind ja offensichtlich, wenn man es entsprechend formatiert.


   Profil
pzktupel
Aktiv Letzter Besuch: in der letzten Woche
Dabei seit: 02.09.2017
Mitteilungen: 2058
Wohnort: Thüringen
  Beitrag No.6, eingetragen 2020-08-26

In Freebasic gibt was ähnliches...nennt sich Case-Anweisung ..aber was soll das Programm genau tun ? Habe so vieles schon geschrieben, aber sehe keine Idee. liste_laufvariable=ermittel_primteiler(laufvariable) liste_pendant=ermittel_primteiler(pendant) #if len(liste_laufvariable)==2 and len(liste_pendant)==2: if 11 in liste_laufvariable and 3 not in liste_laufvariable and 7 not in liste_laufvariable Wenn ichs blicke, wird eine Art Prozedur aufgerufen, die einen Primteiler ermittelt. Wenn es nur um 3,7,11 geht, Könnte man auch 11 als einen Wert speichern. Man prüft , ob 11 MOD liste_laufvariable = 0 oder >0 ist Bei 0 , war die 11 dabei, bei >0 war 3,7 nicht dabei 😐


   Profil
haegar90
Aktiv Letzter Besuch: in der letzten Woche
Dabei seit: 18.03.2019
Mitteilungen: 757
Wohnort: Gog
  Beitrag No.7, eingetragen 2020-08-26

Hallo, du könntest "liste_laufvariable" durch "a" ersetzen.🙃


   Profil
Bekell
Aktiv Letzter Besuch: in der letzten Woche
Dabei seit: 05.09.2008
Mitteilungen: 2517
  Beitrag No.8, vom Themenstarter, eingetragen 2020-08-27

\quoteon(2020-08-26 23:07 - haegar90 in Beitrag No. 7) Hallo, du könntest "liste_laufvariable" durch "a" ersetzen.🙃 \quoteoff Hallo Haegar, habe gerade gelernt, daß man in Programmen der leichteren Verständlichkeit wegen üblicherweise sprechende Variablen und Prozedurennnamen vergib. Das habe ich jetzt eingeführt, damit nicht so viele Rückfragen sind.


   Profil
cramilu
Aktiv Letzter Besuch: in der letzten Woche
Dabei seit: 09.06.2019
Mitteilungen: 1102
Wohnort: Schwäbischer Wald, seit 1989 freiwilliges Exil in Bierfranken
  Beitrag No.9, eingetragen 2020-08-27

Guten Morgen Bekell, allgemein und grundsätzlich solltest Du Dich bezüglich logischer Verknüpfungen unbedingt mit den De-Morgan'schen Gesetzen vertraut machen. Dann hat [DerEinfaeltige] bereits angemerkt, dass auf die schnelle Zeilenumbrüche die Sache schon einmal übersichtlicher machen. Dem Interpreter, Parser oder Compiler ist das bei korrekter Syntax für die Auswertung wurschd! Falls es in Python kein "funktionales IF" gibt, also eine StandardFUNKTION "if(Bedingung)", welche schlicht einen logischen Wert TRUE oder FALSE zurückliefert, der dann an eine zuvor definierte Variable übergeben wird, dann schreibe man sich eine solche selber und nenne sie "f_if" oder so! Danach folgt man erfahrungsgemäß [Scynja]s Vorschlag mit der Kontrollvariable... bVoraussetzung = True // sprechende Kontrollvariable initialisieren bVoraussetzung = bVoraussetzung and f_if("11 in liste_laufvariable") // als Python-Laie kenne ich die genauen Syntaxanforderungen für die Übergabe von Werten an Funktionen leider nicht... bVoraussetzung = bVoraussetzung and f_if("3 not in liste_laufvariable") ... ... und schließlich if bVoraussetzung: [...] // Anwendung des "Statement-IF" Nach meiner inzwischen über 35-jährigen Programmiererfahrung sollte man eingangs eines "Statement-IF" nicht mehr als drei logische Verknüpfungen häufen und das ganze stets unbedingt zeilenweise trennen, wenn die Teilbedingungen auch nur ansatzweise die Fensterbreite sprengen. Liebe Grüße und viel Erfolg weiterhin!


   Profil
DerEinfaeltige
Senior Letzter Besuch: in der letzten Woche
Dabei seit: 11.02.2015
Mitteilungen: 2999
  Beitrag No.10, eingetragen 2020-08-27

Zum Thema any/all: Aus den Pythondocs: \sourceon Python # all(iterable) # Return True if all elements of the iterable are true # (or if the iterable is empty). Equivalent to: def all(iterable): for element in iterable: if not element: return False return True # any(iterable) # Return True if any element of the iterable is true. # If the iterable is empty, return False. Equivalent to: def any(iterable): for element in iterable: if element: return True return False \sourceoff Will man jetzt wissen, ob sich jedes (mindestens ein) Element einer Liste in einer bestimmten Menge befindet, so erzeugt man eben eine entsprechende iterable aus Wahrheitswerten. Kurzes Beispiel: \sourceon Python >>> Menge = {2,3,5,7,11} >>> Liste = [2,4] >>> all(e in Menge for e in Liste) False >>> any(e in Menge for e in Liste) True \sourceoff Natürlich kann ich an any/all auch hardcodierte iterable aus Wahrheitsausdrücken übergeben. \sourceon Python >>> all((True,True,False,True)) False >>> any((True,True,False,True)) True \sourceoff


   Profil
Folgende Antworten hat der Fragesteller vermutlich noch nicht gesehen.
__blackjack__
Aktiv Letzter Besuch: in der letzten Woche
Dabei seit: 23.09.2021
Mitteilungen: 40
  Beitrag No.11, eingetragen 2021-09-26 10:37

Zum einfach nur umformatieren der langen Bedingung würde man besser Klammern statt \ für Zeilenfortsetzung nehmen, das ist unkomplizierter in der Handhabung wenn man etwas an der Bedingung ändert, beispielsweise die Reihenfolge ändert, oder Teilbedingungen hinzufügen oder wegnehmen will: \sourceon python if ( 11 in liste_laufvariable and 3 not in liste_laufvariable and 7 not in liste_laufvariable and 11 not in liste_pendant and len(liste_pendant) > 0 ): \sourceoff Zu den sprechenden Bezeichnern: Die sind schon besser als irgendwelche kryptischen Abkürzungen, aber teilweise nicht wirklich gut. Die sollen ja zum Leser sprechen und dem verraten was der Wert, der hinter dem Namen steckt, im Kontext des Programms bedeutet. `zahl`, `laufvariable`, oder `liste_laufvariable` tun das nicht wirklich. `zahl` scheint beispielsweise eine `obergrenze` zu sein, und `laufvariable` könnte man `zahl` nennen, und `liste_laufvariable` wäre mit `primteiler` deutlich sinnvoller benannt. Bei den `primteiler`\n habe ich den `liste_`-Präfix jetzt weggelassen, weil man Grunddatentypen besser nicht in Namen packt, denn die ändert man während der Programmentwicklung gar nicht so selten. Wenn es um Geschwindigkeit geht, ist eine Liste beispielsweise bei einem ``in``-Test einem `set()` in der Regel unterlegen. Und was anderes wird hier ja nicht mit dem Wert gemacht. Innerhalb von Bedingungen kann man die Teilbedingungen so sortieren, dass die ”billigen” nach vorne rutschen. Test ob ein Container überhaupt Elemente enthält ist in der Regel weniger Rechenaufwand als einen Wert in dem Container zu suchen. Und man kann auch schauen ob man die ``if``-Bedingungen wie in diesem Fall aufteilen kann um Berechnungen zu sparen. Wenn die Teilbedingungen für Pendant oder die Laufvariable nicht erfüllt sind, braucht man die jeweils andere Zahl gar nicht erst in Primteiler zu zerlegen. `ermittel_primteiler()` kann man als „list comprehension“ ausdrücken, oder wenn man diese Zahlen sowieso als Menge haben will, gleich als „set comprehension“. \sourceon python \numberson #!/usr/bin/env python3 from sympy.ntheory import isprime def ermittel_primteiler(x): return {i for i in range(3, x // 2, 2) if x % i == 0 and isprime(i)} def main(): obergrenze = 10_000 trefferanzahl = 0 for nummer, zahl in enumerate(range(3, obergrenze // 2, 10), 1): pendant = obergrenze - zahl - 4 primteiler_von_pendant = ermittel_primteiler(pendant) if primteiler_von_pendant and 11 not in primteiler_von_pendant: primteiler_von_zahl = ermittel_primteiler(zahl) if 11 in primteiler_von_zahl and not primteiler_von_zahl & {3, 7}: trefferanzahl += 1 print( "Nr:", nummer, "Nr1:", trefferanzahl, zahl, "+", pendant, primteiler_von_zahl, primteiler_von_pendant, ) if __name__ == "__main__": main() \sourceoff


   Profil
Bekell wird per Mail über neue Antworten informiert.

Wechsel in ein anderes Forum:
 Suchen    
 
All logos and trademarks in this site are property of their respective owner. The comments are property of their posters, all the rest © 2001-2021 by Matroids Matheplanet
This web site was originally made with PHP-Nuke, a former web portal system written in PHP that seems no longer to be maintained nor supported. PHP-Nuke is Free Software released under the GNU/GPL license.
Ich distanziere mich von rechtswidrigen oder anstößigen Inhalten, die sich trotz aufmerksamer Prüfung hinter hier verwendeten Links verbergen mögen.
Lesen Sie die Nutzungsbedingungen, die Distanzierung, die Datenschutzerklärung und das Impressum.
[Seitenanfang]