Fehler: Attribute Error

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.
supersonic72
User
Beiträge: 17
Registriert: Freitag 15. September 2006, 15:45

Freitag 6. Juli 2007, 13:46

Ich frage mich was dich an der lösung genau stört? Ist sie dir zu langsam?
Bezweifle das es eine Build-in Lösung dafür gibt und empfinde das
Iterieren über float-Werte als ziemlichen Sonderfall.
Ich iteriere über die float Werte, da ich sie später in verschiedene Funktionen ausgeben lasse. Es ist praktisch meine x-Koordinate, wenn man so will. klar könnte ich an jeder Stelle, wo ich p verwende, durch 10 teilen, da ich aber auch eine eingabe wie [0.01,0.02,...] zulassen muss, wird das meiner Meinung nach sehr unbersichtlich.
Ja, hatte aus Geschwindigkeitsgründen auf eine Build-in Lösung gehofft.
Führe mit dem Programm Analysen von großen Datenmengen durch, die im Schnitt 10 Stunden laufen, da macht sich jedes bisschen bemerkbar. Aber mit der .tolist() Variante habe ich mir ja abhilfe geschafft.

Wenn ich die float-Werte miteinander vergleichen will wie

Code: Alles auswählen

0.3==3*0.1
verwende ich inzwischen

Code: Alles auswählen

from decimal import Decimal
Damit habe das Problem behoben. Das existiert ja aber auch nur, wenn ich die Zahlen multipliziere, wenn ich nur die Werte direkt aus der Liste abfrage macht das keine Probleme.
BlackJack

Freitag 6. Juli 2007, 15:13

Wenn Dir das zu unübersichtlich wird, dann stecke es in eine Funktion.

Ich verstehe Deinen Beispielquelltext übrigens nicht so ganz. Zu testen ob ein Element, das man aus einem Container hat, in diesem Container enthalten ist, ist ziemlich witzlos. Natürlich ist `p` in `power_p` enthalten.

Und wenn es Dir auf Laufzeit ankommt, möchtest Du ganz sicher weder ``in`` noch `index()` verwenden. Beides sucht linear vom Anfang der Liste nach dem Wert, wird also mit jedem Schleifendurchlauf langsamer und langsamer. Den Index kann man auch gleich in der äusseren Schleife mitzählen:

Code: Alles auswählen

    for p_index, p in enumerate(power_p):
        # ...
Falls `power_p` sehr viele Werte enthält, könnte man auch eine Generatorfunktion oder ein Sequenz-Objekt dafür schreiben um Speicherplatz zu sparen.

`arange()` schützt nicht vor dem Problem mit dem multiplizieren:

Code: Alles auswählen

In [27]: a = numpy.arange(0, 0.5, 0.1)

In [28]: a
Out[28]: array([ 0. ,  0.1,  0.2,  0.3,  0.4])

In [29]: 0.3 in a
Out[29]: False
supersonic72
User
Beiträge: 17
Registriert: Freitag 15. September 2006, 15:45

Freitag 6. Juli 2007, 15:26

Wenn Dir das zu unübersichtlich wird, dann stecke es in eine Funktion.
Ich bin mir immer unsicher, was mehr Zeit verbraucht, wenn ich die Funktionen auslager oder sie direkt in das Programm schreibe.
Und wenn es Dir auf Laufzeit ankommt, möchtest Du ganz sicher weder ``in`` noch `index()` verwenden. Beides sucht linear vom Anfang der Liste nach dem Wert, wird also mit jedem Schleifendurchlauf langsamer und langsamer. Den Index kann man auch gleich in der äusseren Schleife mitzählen:
Danke für den Tip. Die Enumerate Funktion ist genau das, was ich gesucht habe. Wusste nicht, wie ich das jeweils mitzählen konnte. Werde das gleich mal einarbeiten und schauen, ob es Zeit spart.
Falls `power_p` sehr viele Werte enthält, könnte man auch eine Generatorfunktion oder ein Sequenz-Objekt dafür schreiben um Speicherplatz zu sparen.
Was versteht man unter einer Generator-Funktion oder einem Sequenzobjekt? power_p enthält im Schnitt 100 Werte.
`arange()` schützt nicht vor dem Problem mit dem multiplizieren:
Ich weiß, dafür verwende ich Decimal, und das funktioniert.

Danke nochmal für die vielen hilfreichen Anregungen.
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Freitag 6. Juli 2007, 15:38

Ein Generator ist quasi eine On-Demand-Sequenz, die nur Werte ausgibt, wenn sie angefordert werden. Das kann eine einfache Funktion sein:

Code: Alles auswählen

def generate_range(stop):
    i = 0
    while i < stop:
        yield i
        i += 1
Anstelle von `return` wird das `yield`-Statement verwendet, das zwar einen Wert liefert, die Funktion danach aber weiterlaufen lässt.

Anwendung:

Code: Alles auswählen

numbers = generate_range(10)
for number in numbers:
    print number
Im Gegensatz zu normalen Sequenzen wie Tupeln oder Listen hat ein Generator aber keine Länge, da die Werte nur schrittweise ausgegeben werden; um sie zu erhalten (d.h. `len()` darauf anwenden zu können), muss man den Generator erst mit `tuple()` oder `list()` in eine Sequenz umwandeln.

Interna: Bei jedem Schleifendurchlauf wird die Methode `next()` des Generators aufgerufen; wirft sie eine `StopIteration`(?)-Exception, wird die Schleife verlassen.

Einer der Vorteile eines Generators besteht nun darin, dass seine Ausgabe schrittweise und nicht auf einmal erzeugt wird. Werden die Daten direkt weiter verarbeitet, müssen sie gar nicht erst in einer Liste zwischengespeichert werden. Je nach Umfang der Daten kann das einen großen Unterschied im Speicherverbrauch darstellen.
Antworten