For Schleife?

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.
Antworten
diego2k
User
Beiträge: 6
Registriert: Sonntag 22. November 2009, 12:15

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

Code: Alles auswählen

(q for q in primes if not current_prime.divides(q))
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

Code: Alles auswählen

(q for q in primes if not current_prime.divides(q))
wie würde diese Zeile in C aussehen?
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Das Sollte gar nicht funktionieren weil yield auserhalb einer Funktion ist
the more they change the more they stay the same
diego2k
User
Beiträge: 6
Registriert: Sonntag 22. November 2009, 12:15

jab schon klar, war nur als bsp.
das ganze ist natürlich innerhalb einer Funktion
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

diego2k hat geschrieben:Wie kann das sein?
bzw was macht das
Kann man nicht sagen, ohne den vollständigen code zu kennen.

Code: Alles auswählen

(q for q in primes if not current_prime.divides(q))
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
diego2k
User
Beiträge: 6
Registriert: Sonntag 22. November 2009, 12:15

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 ...
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.
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.
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

Wird Zeit, dass die Closures, die Apple in C eingeführt hat mal standadisiert werden. ;)
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".
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

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.
diego2k
User
Beiträge: 6
Registriert: Sonntag 22. November 2009, 12:15

Ich wollte ein C Bsp, dass ich sehe was hier eigentlich passiert. Außerdem is C sehr verbreitet.

Herzlichen danke für eure Antworten
Antworten