Seite 1 von 1
For Schleife?
Verfasst: Montag 14. Dezember 2009, 20:51
von diego2k
Hallo,
ich benötige python hauptsächlich für SAGE, nun bin ich auf folgendes gestoßen:
(primes ist ein generator mit allen natürlichen Zahlen)
Code: Alles auswählen
while True:
current_prime = primes.next()
yield current_prime
primes = (q for q in primes if not current_prime.divides(q))
das ganze soll alle Primzahlen zurück liefer, das tut es aber nur wenn das
in einer eigenen Funtkion steht
zb:
Code: Alles auswählen
def funk(primes,current_prime):
return (q for q in primes if not current_prime.divides(q))
while True:
current_prime = primes.next()
yield current_prime
primes =funk(primes,current_prime)
Wie kann das sein?
bzw was macht das
wie würde diese Zeile in C aussehen?
Verfasst: Montag 14. Dezember 2009, 20:53
von Dav1d
Das Sollte gar nicht funktionieren weil yield auserhalb einer Funktion ist
Verfasst: Montag 14. Dezember 2009, 21:02
von diego2k
jab schon klar, war nur als bsp.
das ganze ist natürlich innerhalb einer Funktion
Re: For Schleife?
Verfasst: Montag 14. Dezember 2009, 22:06
von Darii
diego2k hat geschrieben:Wie kann das sein?
bzw was macht das
Kann man nicht sagen, ohne den vollständigen code zu kennen.
wie würde diese Zeile in C aussehen?
Da es in C keine Generatoren gibt, ist das schlecht zu übertragen, der Ausdruck entspricht einem
Code: Alles auswählen
def generator():
for q in primes:
if not current_prime.divides(q): yield q
generator()
in python
Verfasst: Montag 14. Dezember 2009, 22:40
von diego2k
Danke!
aber was ich nicht verstehe:
Code: Alles auswählen
def generator(primes,current_prime):
for q in primes:
if not current_prime.divides(q): yield q
def numbers():
i = 2
while True:
yield i
i += 1
def my_primes():
primes = numbers()
while True:
current_prime = primes.next()
yield current_prime
primes = generator(primes,current_prime)
dieser Code funtkioniert ohne Probleme.
Wenn ich jetzt ab so schreibe:
Code: Alles auswählen
def my_primes():
primes = numbers()
while True:
current_prime = primes.next()
yield current_prime
primes = (q*q for q in primes if not current_prime.divides(q))
bekomm ich nur mehr die "numbers" als:
2,3,4,5,6,7 usw
Wobei er es beim ersten Schleifendurchlauf aber richtig macht,
also wenn das erste mal die while begonnen wird und das erste mal die primes ausgerechnet werden, scheinen diese wirklich zu stimmen.
Sobald die Schleife das 2. mal begonnen wird,
also das 2. mal die primes mit
(q*q for q in primes if not current_prime.divides(q))
erstellt werden, kommt die vorlaufende Reihe raus ...
Verfasst: Dienstag 15. Dezember 2009, 06:14
von BlackJack
@diego2k: Schreib Dir den Ablauf am besten mal auf einem Blatt Papier auf. Dann wird Dir zum Beispiel auffallen, dass bei der nichtfunktionierenden Variante immer nur *ein* `current_prime` existiert, dass immer wieder überschrieben wird, während beim Aufruf von `generator()` die ganzen `current_primes` als lokale Variablen des jeweiligen Funktionsaufrufes weiterexistieren.
Verfasst: Dienstag 15. Dezember 2009, 08:42
von BlackJack
@diego2k: Du fragtest ja wie das in C aussieht. C hat keine Generatoren, also muss man die mit Klassen nachbauen. Ups, C hat ja auch keine Klassen. Closures auch nicht. Also muss man's notdürftig mit ``struct``\s nachbasteln. Könnte so aussehen:
Code: Alles auswählen
#include <inttypes.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
/* ---------------------------------------------------------------
* Iterator base type.
*/
struct Iterator;
typedef uint32_t (*next_func_t) (struct Iterator*);
typedef struct Iterator {
next_func_t next;
} Iterator;
/* ---------------------------------------------------------------
* Simple counter type.
*/
typedef struct {
Iterator base_type;
uint32_t current;
} Counter;
uint32_t Counter_next(Counter *counter)
{
return counter->current++;
}
void Counter_init(Counter *counter, uint32_t start_value)
{
counter->base_type.next = (next_func_t) Counter_next;
counter->current = start_value;
}
/* ---------------------------------------------------------------
* Dividable filter type.
*/
typedef struct Filter {
Iterator base_type;
Iterator *previous;
uint32_t prime;
} Filter;
uint32_t Filter_next(Iterator *iterator)
{
uint32_t i;
Filter *filter = (Filter*) iterator;
while (true) {
i = filter->previous->next(filter->previous);
if (i % filter->prime) return i;
}
}
Iterator* Filter_create(Iterator *previous, uint32_t prime)
{
Filter *result = (Filter*) malloc(sizeof(*result));
result->base_type.next = Filter_next;
result->previous = previous;
result->prime = prime;
return (Iterator*) result;
}
/* ---------------------------------------------------------------
* Here's the action. :-)
*/
int main(void)
{
Counter numbers;
Iterator *primes;
uint32_t prime;
Counter_init(&numbers, 2);
primes = (Iterator*) &numbers;
while (true) {
prime = primes->next(primes);
printf("%d,", prime);
primes = Filter_create(primes, prime);
}
}
Funktioniert grundsätzlich, mit zwei Einschränkungen: 1. Der `Counter` springt irgendwann wieder auf 0, wenn der 32-Bit-Zahlenbereich ausgeschöpft ist und 2. gibt's keine Möglichkeit den angeforderten Speicher für die `Filter`-Objekte wieder freizugeben. Da hätte man dem `Iterator` noch eine "virtuelle `free()`-Methode" spendieren müssen. Aber es geht ja auch nur um die Demonstration, wie das grundsätzlich in C aussehen würde.
Verfasst: Dienstag 15. Dezember 2009, 09:37
von Darii
Wird Zeit, dass die Closures, die Apple in C eingeführt hat mal standadisiert werden.

Verfasst: Dienstag 15. Dezember 2009, 11:38
von BlackJack
Ich weiss nicht so recht. Ich finde die Syntax nicht schön und möchte ausserdem nicht, dass C zu so einem unverständlichen Featuremonster wird wie C++0x. C ist ein guter "plattformunabhängiger Makroassembler". Wer mehr will oder braucht, soll zu einer höheren Sprache greifen, und nicht anfangen alle möglichen Konzepte an C "dranzutackern".
Verfasst: Dienstag 15. Dezember 2009, 13:04
von Darii
BlackJack hat geschrieben:Ich finde die Syntax nicht schön
Muss ja auch zum Rest der Sprache passen

*scnr*
und möchte ausserdem nicht, dass C zu so einem unverständlichen Featuremonster wird wie C++0x. C ist ein guter "plattformunabhängiger Makroassembler". Wer mehr will oder braucht, soll zu einer höheren Sprache greifen, und nicht anfangen alle möglichen Konzepte an C "dranzutackern".
Die Closures wurde ja hauptsächlich für ObjC und GCD(systemweiter Threadpool in MacOS) eingebaut und dafür ist es ok. Auch sonst finde ich das eine gute Ergänzung, mit der man viel machen kann und es ist ja trotzdem noch recht low-level.
Verfasst: Mittwoch 16. Dezember 2009, 17:59
von diego2k
Ich wollte ein C Bsp, dass ich sehe was hier eigentlich passiert. Außerdem is C sehr verbreitet.
Herzlichen danke für eure Antworten