Seite 1 von 1

Python optimiert selbstständig?

Verfasst: Sonntag 23. Juli 2006, 19:50
von thelittlebug
Beim Profilen ( verwende ich zum Durchzählen ob die Rekursion auch wirklich passt ) meines Backtracking Scripts bin ich auf etwas sonderbares gestoßen.
Kann es sein das Python IF's automatisch optimiert?

Code: Alles auswählen

a = 0
b = 1
c = 1

if ( a and b and c )
Nun wird er in meinem Beispiel b und c niemals auf true prüfen. Hab ich das richtig erkannt? Falls es doch nicht so ist hab ich glaub ich ein Problem :D

lg tlb

p.s. der code tag ist praktisch :)

Re: Python optimiert selbstständig?

Verfasst: Sonntag 23. Juli 2006, 20:48
von gerold
thelittlebug hat geschrieben:

Code: Alles auswählen

a = 0
b = 1
c = 1

if ( a and b and c )
Nun wird er in meinem Beispiel b und c niemals auf true prüfen. Hab ich das richtig erkannt?
Hi!

Du hast das schon richtig verstanden. Das ist bei Python das normale Verhalten.

Da der Ausdruck ``a and b and c`` nur dann True ergeben kann, wenn ``a``, ``b`` und ``c`` True sind, genügt das erste Auftreten eines False-Ausdrucks um die Prüfung abzubrechen und ein False zurück zu geben. Du hast recht. ``b`` und ``c`` werden nicht mehr ausgewertet, da ``a`` bereits False ist.

Es ist sogar so, dass nicht wirklich ein ``False`` zurück gegeben wird, sondern der Wert des ersten Ausdrucks, der für den Abbruch der Prüfung gesorgt hat.

Code: Alles auswählen

>>> a = 0
>>> b = 1
>>> c = 2
>>> a and b and c
0
>>> b and c
2
>>> 
http://docs.python.org/lib/boolean.html

mfg
Gerold
:-)

Verfasst: Sonntag 23. Juli 2006, 21:18
von BlackJack
Kleines unwichtiges Detail noch: Nicht das ``if`` wird optimiert, sondern ``and`` und ``or``.

Verfasst: Sonntag 23. Juli 2006, 22:00
von thelittlebug
Danke für die Aufklärung.

Ich dachte schon ich seh nicht richtig :)
Am Anfang ist man halt bereits mit/durch kleinem/s überfordert

mfg tlb

Verfasst: Sonntag 23. Juli 2006, 23:17
von birkenfeld
Optimiert wird da eigentlich gar nix. Dieses Verhalten ist so spezifiziert und wird wie in vielen Programmiersprachen (also z.B. nicht V.B.) so implementiert, einfach weil es sinnvoll ist. (Stichwort short-circuited boolean evaluation)

Verfasst: Montag 24. Juli 2006, 12:12
von keppla
Stichwort short-circuited boolean evaluation
Auch recht häufig gehört: "Lazy evaluation".

Verfasst: Montag 24. Juli 2006, 12:50
von Leonidas
keppla hat geschrieben:Auch recht häufig gehört: "Lazy evaluation".
Das ist aber was ganz anderes. Generatoren sind zum beispiel lazy evaluated, da ihre Werte erst dann zur Verfügung stehen wenn sie gebraucht werden, nicht schon vorher. Vergleiche range() mit xrange().

Verfasst: Montag 24. Juli 2006, 13:49
von keppla
was "ganz anderes" würde ich nicht unbedingt sagen. Abstrakt gesprochen heist lazy evaluation afaik, dass man einen baum hat, der ausgewertet werden soll, und dass nur die nötigen zweige betrachtet werden.

Verfasst: Montag 24. Juli 2006, 19:43
von Joghurt
Ja, aber gerade das macht Python nicht:

Code: Alles auswählen

def f(x):
 return x**0.4+2*x
liste = [f(x) for x in range(100)]
print liste[50]
Python ruft hier f 100 mal auf. Eine Sprache mit Lazy Evaluation würde nur f(50) aufrufen.

Schau dir z.B. mal Haskell an. Dort kannst du auch ohne Probleme unendlich große Listen, z.B. die Liste aller Primzahlen definieren, weil nur die Elemente ausgewertet werden, die wirklich benötigt werden.

Verfasst: Montag 24. Juli 2006, 19:59
von Rebecca
Joghurt hat geschrieben:Dort kannst du auch ohne Probleme unendlich große Listen, z.B. die Liste aller Primzahlen definieren.
Ui! Dann koenntest du nebenbei eventuell noch den Abel-Preis fuer Mathematik einheimsen, weil du der erste waerest, der eine Formel zur Berechnung von Primzahlen gefunden hat. :wink:

Verfasst: Montag 24. Juli 2006, 20:12
von Joghurt
Das hat ein Gewisser Eratosthenes vor über 2000 Jahren gemacht.

Verfasst: Dienstag 25. Juli 2006, 07:36
von Rebecca
Das, was Eratosthenes gemacht hat, war ein besonders schlauer Algorithmus, aus einem endlichen Intervall [2, n] alle Primzahlen rauszufinden, indem man nach und nach alle nicht-Primzahlen ausschliesst. Es ist die etwas schlauere Variante zu "Teste bei jeder Zahl, ob sie durch irgendwas anderes als eins und sich selbst teilbar ist". Das ganze nennt sich Sieb des Erastosthenes. Es ist aber keine Formel zur Berechnung neuer Primzahlen, und man kann somit nicht unendlich viele Primzahlen angeben (nur beliebig viele).

Nicht umsonst kann man die Freizeit seines Rechners auch zum Berechnen der naechsten unbekannten Primzahl opfern statt zur Suche nach ausserirdischer Intelligenz. Laut Wikipedia ist die groesste zurzeit bekannte Primzahl 2^30402457 − 1. Oh, und ich sehe gerade:
Wikipedia hat geschrieben:Für den ersten Primzahlbeweis einer Zahl mit mehr als 10 Millionen Dezimalstellen hat die Electronic Frontier Foundation einen Preis von 100.000 US-Dollar ausgeschrieben.
Also ranhalten, Leute! :wink:

Verfasst: Dienstag 25. Juli 2006, 09:16
von BlackJack
Rebecca hat geschrieben:Das, was Eratosthenes gemacht hat, war ein besonders schlauer Algorithmus, aus einem endlichen Intervall [2, n] alle Primzahlen rauszufinden, indem man nach und nach alle nicht-Primzahlen ausschliesst. Es ist die etwas schlauere Variante zu "Teste bei jeder Zahl, ob sie durch irgendwas anderes als eins und sich selbst teilbar ist". Das ganze nennt sich Sieb des Erastosthenes. Es ist aber keine Formel zur Berechnung neuer Primzahlen, und man kann somit nicht unendlich viele Primzahlen angeben (nur beliebig viele).
Man kann aber problemlos mathematisch bzw. in Haskell eine Liste mit allen Primzahlen definieren. Und nur das hat Joghurt behauptet. Nicht das er eine effiziente Formel zur direkten Berechnung der n-ten Primzahl hat.

Hier ist die Definition des Siebs und der Liste aller Primzahlen in Haskell:

Code: Alles auswählen

sieve (x:xs) = x : sieve [n | n <- xs, mod n x /= 0]
sieve _      = []

all_primes = sieve [2..]
Und im Interpreter sieht's dann so aus:

Code: Alles auswählen

$ ghci primes.hs
   ___         ___ _
  / _ \ /\  /\/ __(_)
 / /_\// /_/ / /  | |      GHC Interactive, version 6.4.1, for Haskell 98.
/ /_\\/ __  / /___| |      http://www.haskell.org/ghc/
\____/\/ /_/\____/|_|      Type :? for help.

Loading package base-1.0 ... linking ... done.
Compiling Main             ( prime.hs, interpreted )
Ok, modules loaded: Main.
*Main> sieve [2..100]
[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]
*Main> all_primes
[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,
83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,
163,167,173,179,181,191,193,197,199,211,223,227,229,233,
239,241,251,257,263,269,271,277,281,283,293,307,311,313,
317,331,337,347,349,353,359,367,373,379,383,389,397,401,
409,419,421,431,433,439,443,449,457,461,463,467,479,487,
...
Das läuft ewig so weiter bis man das Programm abbricht, oder der Speicher aufgebraucht ist.

Verfasst: Dienstag 25. Juli 2006, 20:32
von keppla
Ja, aber gerade das macht Python nicht
In diesem beispiel nicht, aber da hast du ja auch keine Baumstruktur zugrunde liegen, afaik

aber z.B. in

Code: Alles auswählen

print (False or True) or doCalculation
hat man eine.

Wie gesagt: kommt drauf an, was man unter Lazy Evaluation versteht.

Verfasst: Dienstag 25. Juli 2006, 20:38
von thelittlebug
ist nicht alles ein baum?
sogar 1+1?

siehe lisp?

mfg tlb

Verfasst: Dienstag 25. Juli 2006, 22:55
von keppla
ist nicht alles ein baum?
sogar 1+1?
Ja, klar! Deshalb sage ich ja auch, dass True or willNeverBeExecuted() der lazy evaluation zum Opfer fällt.