Brauche bitte Hilfe

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
holgi74
User
Beiträge: 2
Registriert: Sonntag 16. März 2008, 22:49
Kontaktdaten:

Hallo

habe folgendes Script, dass am Ende einen Text auf dem Bildschirm ausgibt. Ich möchte aber zusätzlich die Speicherung in eine Datei z.B. output.txt
Wer kann mir helfen?

Code: Alles auswählen

# Neuen Text erstellen

CurWort = 'Der'
LenText = 200
Text = CurWort

for n in range(LenText):
    x = random()
    ProbSum = 0
    for (NextWort, Prob) in WortDict[CurWort].items():
        if (x>=ProbSum) and (x < ProbSum+Prob):
            Text += " " + NextWort
            CurWort = NextWort
        ProbSum += Prob

print Text[:Text.rfind('.')+1]
z = raw_input('Enter beendet das Programm. ')
Zuletzt geändert von holgi74 am Montag 22. September 2008, 19:51, insgesamt 1-mal geändert.
[url=http://www.hardlab.de/]Handy News[/url]
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Hallo holgi74, willkommen im Forum,

Erstmal formales: du hast ins falsche Unterforum gepostet. Ich werds verschieben, aber ändere doch bitte den Titel des Threads und schreib dort was sinnvolles rein.

Zweitens: dieser ``raw_input``-Trick um das Fenster offen zu halten funktioniert nicht immer richtig und ist auch Quatsch. Schau in die FAQ, dort steht wie man Skripte richtig startet.

Drittens: Wenn du die FAQ gelesen hast kannst du mit ``python deinskript.py > dateiname.txt`` die Ausgaben deines Programmes in eine Datei reinschreiben.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
holgi74
User
Beiträge: 2
Registriert: Sonntag 16. März 2008, 22:49
Kontaktdaten:

Danke für die Infos. Werde mir die FAQ mal in ruhe durchlesen.

Viele Grüße
BlackJack

Und dann wäre ein Blick in den Style Guide vielleicht eine gute Idee.

Wenn man die Liste der Zahlen nicht braucht, ist `xrange()` speicherschonender.

Bei der Namensgebung hättest Du weniger abkürzen und Dich auf eine Sprache beschränken können, `NextWort` klingt irgendwie nicht so toll.

Aufauen einer Zeichenkette mittels wiederholtem ``+=`` kann recht ineffizient werden. Üblicherweise sammelt man die Einzelteile in einer Liste und benutzt am Ende die `join()`-Methode auf Zeichenketten.

Die ``if``-Bedingung lässt sich einfacher ohne ``and`` ausdrücken.

Ungetestet:

Code: Alles auswählen

def create_text(word2probability, length=200, start_word='Der'):
    current_word = start_word
    result = [current_word]
    for dummy in xrange(length):
        x = random()
        probability_sum = 0
        for next_word, probability in word2probability[current_word].items():
            if probability_sum < x < probability_sum + probability:
                result.append(next_word)
                current_word = next_word
            probability_sum += probability
    
    result = ' '.join(result)
    return result[:result.rfind('.') + 1]
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

BlackJack hat geschrieben:Aufbauen einer Zeichenkette mittels wiederholtem ``+=`` kann recht ineffizient werden. Üblicherweise sammelt man die Einzelteile in einer Liste und benutzt am Ende die `join()`-Methode auf Zeichenketten.
Liest man ja immer wieder. Hab mal experimentiert:

Code: Alles auswählen

import time, profile, cProfile

def string_add():
    s = ""
    for k in xrange(anz): s+=str(k)

def list_app():
    l = list()
    for k in xrange(anz): l.append(str(k))
    s = "".join(l)

def list_comp():
    s = "".join([str(k) for k in xrange(anz)])

anz = 100000  # 100.000
profile.run("string_add(); list_app(); list_comp()")
cProfile.run("string_add(); list_app(); list_comp()")

anz = 1000000  # 1.000.000
for func in [string_add,list_app,list_comp]:
    time0 = time.time()
    func()
    print "%10s: %.2f sec" %(func.__name__,time.time()-time0)
Dabei ist folgendes herausgekommen (gekürzte Fassung):

Code: Alles auswählen

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.316    0.316    0.344    0.344 speedtest.py:12(list_comp)
        1    0.284    0.284    0.284    0.284 speedtest.py:3(string_add)
        1    1.812    1.812    3.112    3.112 speedtest.py:7(list_app)

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.266    0.266    0.285    0.285 speedtest.py:12(list_comp)
        1    0.338    0.338    0.338    0.338 speedtest.py:3(string_add)
        1    0.567    0.567    0.805    0.805 speedtest.py:7(list_app)

string_add: 3.56 sec
  list_app: 3.71 sec
 list_comp: 3.51 sec
Unterschiede in den absoluten Zeiten bei den verschiedenen Testverfahren machen mir kein Problem; aber die relativen Zeiten. Das einzige, was demnach wirklich sicher zu sein scheint, ist, dass die Variante mit dem append() die schlechteste Performance erreicht. Zeichenketten"addition" und LC tun sich wenig. Je nach "Profiler" liegt mal die eine, mal die andere vorne.

Ist mein Testverfahren grundsätzlich unbrauchbar?
Oder ist die Ergebniszeichenkette mit 488890 Zeichen immer noch zu kurz?
Gibt es andere Szenarien, wo eine Zeichenketten"addition" klar verliert?
BlackJack

Nicht unbrauchbar, Du musst aber auch dazu sagen mit welcher Python-Version. Das Zeichenkettenobjekte auf die es nur eine Referenz gibt, bei dieser Operation doch "mutiert" werden, es merkt ja keiner, ist ein Implementierungsdetail von aktuellen CPython-Versionen. Man spart sich so das Erzeugen eines neuen Python-Objekts und beim `realloc()` unter der Haube müssen auch die alten Zeichenketten-Daten von der ersten Zeichenkette nicht unbedingt umkopiert werden.
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

pütone hat geschrieben:Gibt es andere Szenarien, wo eine Zeichenketten"addition" klar verliert?
Andere Python-Implementationen als CPython. In CPython ist es so optimiert, daß "a" + "b" keinen Overhead produziert. In anderen Implementationen (Jython, Ironpython, ...) kann das anders aussehen.
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

Scheint das Verhalten auch OS-abhängig zu sein?
Also auf dem WindowsXP Rechner auf dem ich arbeite (CPython 2.5) kommt das hier raus:

Code: Alles auswählen

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.110    0.110    0.113    0.113 add_vs_join.py:12(list_comp)
        1    0.139    0.139    0.139    0.139 add_vs_join.py:3(string_add)
        1    0.536    0.536    0.805    0.805 add_vs_join.py:7(list_app)

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.108    0.108    0.111    0.111 add_vs_join.py:12(list_comp)
        1    0.137    0.137    0.137    0.137 add_vs_join.py:3(string_add)
        1    0.175    0.175    0.222    0.222 add_vs_join.py:7(list_app)

string_add: 6.91 sec
  list_app: 1.53 sec
 list_comp: 1.26 sec
Die Steigerung von 100.000 auf 1.000.000 Durchläufe scheint der add Funktion ganz schön zuzusetzen.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Zap hat geschrieben:Scheint das Verhalten auch OS-abhängig zu sein?
Sieht ganz so aus. Bei 1 Mio. Durchläufen ergibt sich bei mir (alles auf demselben Rechner):

Code: Alles auswählen

Linux Kernel 2.6.13, CPython 2.4.1:
string_add: 2.58 sec
  list_app: 3.06 sec
 list_comp: 2.34 sec

Linux Kernel 2.6.13, CPython 2.5.1:
string_add: 3.10 sec
  list_app: 3.51 sec
 list_comp: 3.06 sec

Linux Kernel 2.6.18, CPython 2.5:
string_add: 2.88 sec
  list_app: 3.43 sec
 list_comp: 2.96 sec

Linux Kernel 2.6.22, CPython 2.5.1:
string_add: 3.27 sec
  list_app: 2.91 sec
 list_comp: 2.33 sec
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Bei mir ist die String-Methode dennoch langsamer.

Code: Alles auswählen

Linux Kernel 2.6.18, CPython 2.5.2:
string_add: 1.42 sec
  list_app: 0.85 sec
 list_comp: 0.73 sec

Linux Kernel 2.6.24, CPython 2.4.4:
string_add: 1.06 sec
  list_app: 1.04 sec
 list_comp: 0.80 sec
(könnte noch einige ähnliche Kisten testen, aber das reicht schon)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten