Der "Print"-Befehl bei Phython 3.2

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
IlsePlenski
User
Beiträge: 2
Registriert: Montag 16. Januar 2012, 17:42

Hey Leute,
ich bin ein relativer Neuling, was Python angeht und hatte bis jetzt Python 2.5 und Python 2.7 mit Python Shell und SPE benutzt.
Jetzt wollte ich mal Python 3.2 ausprobieren und mir die Änderungen ansehen.
Doch beim print-Befehl stoß ich auf folgendes Problem:
Ich kann keine Reihen mehr in den Schleifen machen...
OK damit ihrs versteht ein kurzer Code:

Code: Alles auswählen

for i in range(5):
     print "Hi",
durch das Komma sollte das Ergebinis so aussehen:

Code: Alles auswählen

HiHiHiHi
Klar beim neuen Print muss man auch dazu noch die Klammern benutzten, aber sowohl

Code: Alles auswählen

for i in range(5):
     print ("Hi",)
als auch

Code: Alles auswählen

for i in range(5):
     print ("Hi"),
funktionieren nicht!

Als Ergebnis bekomme ich nur:

Code: Alles auswählen

Hi
Hi 
Hi
Hi
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Ein Blick in die Doku offenbahrt die Parameter, die die `print`-Funktion akzeptiert. Da findet man den `end`-Parameter, der per default auf "\n" steht. Man muss diesen also verändern:

Code: Alles auswählen

In [2]: for _ in range(5):
   ...:     print("Hi", end="")
   ...:     
HiHiHiHiHi
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
IlsePlenski
User
Beiträge: 2
Registriert: Montag 16. Januar 2012, 17:42

jap :lol:
so klappts, ich danke vielmals für die schnelle Antwort! :D
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

Ach ja, nur zur Info ;)

Code: Alles auswählen

In [32]: for i in range(5):
   ....:     print "Hi",
   ....:     
   ....:     
Hi Hi Hi Hi Hi
Man beachte die Leerzeichen zwischen den „His“.
problembär

nomnom hat geschrieben:Ach ja, nur zur Info ;)

Code: Alles auswählen

In [32]: for i in range(5):
   ....:     print "Hi",
   ....:     
   ....:     
Hi Hi Hi Hi Hi
Man beachte die Leerzeichen zwischen den „His“.
Das ist in der Tat ein Problem (das aber relativ selten auftritt und das auch in Ordnung geht, denn dafür hat man bei Pythons print-Befehl auch viele Bequemlichkeitsvorteile). Ich löse das meistens so:

Code: Alles auswählen

a = ""
for i in range(5):
    a += "Hi"
print a
Aber vielleicht hat jemand noch einen anderen/besseren Vorschlag? Sehe gerade nicht, wie das z.B. mit ".join()" einfacher gehen sollte ...
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

Code: Alles auswählen

In [9]: print 'Hi'*5
HiHiHiHiHi
In [10]: print ''.join(itertools.repeat('Hi', 5)) # oder mit str.join
HiHiHiHiHi
Zuletzt geändert von nomnom am Montag 16. Januar 2012, 20:43, insgesamt 1-mal geändert.
deets

problembär hat geschrieben: Das ist in der Tat ein Problem (das aber relativ selten auftritt und das auch in Ordnung geht, denn dafür hat man bei Pythons print-Befehl auch viele Bequemlichkeitsvorteile). Ich löse das meistens so:

Code: Alles auswählen

a = ""
for i in range(5):
    a += "Hi"
print a
Aber vielleicht hat jemand noch einen anderen/besseren Vorschlag? Sehe gerade nicht, wie das z.B. mit ".join()" einfacher gehen sollte ...
Und da war er wieder, Koenig quadratische Laufzeit. Merke: kein Problem kann zu simpel sein, als das es nicht noch schlechter geloest werden koennte!
problembär

Code: Alles auswählen

print 5 * "Hi"
ist natürlich recht cool. Das geht aber nur in diesem Beispiel, normalerweise will man auch andere Strings ohne "\n" oder Leerzeichen dazwischen ausgeben.
Ach, könnt' man vielleicht wirklich mal '"".join(("a", "b"))' verwenden. Sieht aber auch irgendwie blöd aus. :(
Na ja, ist sowieso wie gesagt recht selten. Hauptsache, man kommt drumrum. Performanceprobleme wegen des +-Operators auf Strings hatte ich jedenfalls noch nie. Sollten sie mal auftreten, was sie nicht tun, dann würde ich mir eine andere Lösung überlegen. Solange verwende ich den Operator weiter, denn er macht den Code sehr übersichtlich.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

problembär hat geschrieben:Sollten sie mal auftreten, was sie nicht tun, dann würde ich mir eine andere Lösung überlegen. Solange verwende ich den Operator weiter, denn er macht den Code sehr übersichtlich.
Du solltest Sprecher der Atom-Lobby werden :twisted:

Aber mal ernsthaft: Findest Du Strings per "+" zusammengesetzt wirklich übersichtlicher, als die Trennung in Platzhalter und Daten? Ich meine jede Templatesprache basiert auf diesem Pattern und letztlich ist das bei `"".format()` auch nichts anderes. Ich habe bspw. bei Java immer meine Probleme damit, dass man dort Strings per "+" zusammenbaut (was nebenbei bei Java performant ist aufgrund der anderen Konzeption von Strings!).
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
lunar

@Hyperion: "String.format()" und "System.out.printf()" gibt es auch in Java :) "+" verwendet man eigentlich nur, um Zeichenkettenliterale umzubrechen. Und darum sollte sich die IDE kümmern, wenn Du innerhalb eines Zeichenkettenliterals die Eingabe-Taste betätigst. Genau genommen ist "+" auch nicht performant, aber ich nehme an, dass wolltest Du auch sagen.

Ansonsten ist diese Diskussion schon wieder überflüssig, Du wirst problembär ohnehin nicht überzeugen, und der Vorteil der Alternativen zu "+" ist schon hinreichend klar gestellt.
BlackJack

@lunar: Ich würde erwarten, dass ``+`` in Java performant ist. Falls nicht, verwendet man den falschen Compiler. Bei Konstanten kann der die Operation zur Übersetzungszeit ausführen und wenn man Variablen und mehrere ``+`` verwendet, dann erwarte ich, dass der hinter den Kulissen Code mit einem `StringBuilder` [1]_ erzeugt.

[1] Oder was immer auch die nicht-thread-safe-Variante von der entsprechenden Klasse ist.
lunar

@BlackJack: Stimmt, ich habe nicht daran gedacht, dass man diesen Operator zu StringBuilder-Aufrufen kompilieren kann. So gesehen hast Du natürlich recht.
deets

Tatsaechlich scheint Python da auch schon was zu optimieren. Zumindest habe ich mal ein kleines bisschen timing-tests gemacht, und da war string.join nicht wirklich schneller.

Allerdings war es frueher definitiv nicht so:

http://www.skymind.com/~ocrow/python_string/

Und laut

http://docs.python.org/library/stdtypes ... fer-xrange

ist das auch kein garantiertes Verhalten. Ein garantiertes Verhalten ist aber natuerlich, dass problembaerchen nix aendern wird...
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Die String-Optimierungen in Python sind meines Wissens nach wie vor ein Implementierungsdetail von CPython. Wurde zwar schon von deets angerissen, soll aber nochmal betont werden. Nichtsdestotrotz kann es Situationen geben, wo man nur 2-3 Strings zusammensetzen will und einem `str.join()` vielleicht wirklich umständlicher erscheint.
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

deets hat geschrieben:Tatsaechlich scheint Python da auch schon was zu optimieren. Zumindest habe ich mal ein kleines bisschen timing-tests gemacht, und da war string.join nicht wirklich schneller.
Es ist zumindest nicht dramatisch, wenn du beispielsweise einhundert Stringverkettungen mit je 10 Zeichen durchführst. Mit nicht dramatisch meine ich hier etwa Faktor 3.

Führst du die Stringverkettung aber zehntausendmal mit einem String aus, dann landest du bei Faktor 150 oder höher. Machst du dann den hinzuzufügenden String 40 Zeichen lang, statt 10 Zeichen, dann ändert sich die Zeit für die Liste nicht sinnvoll messbar, die Stringverkettung braucht dann aber etwa die vierfache Zeit, also Faktor 600.

Code: Alles auswählen

def str_cat(repeat, runs=1):
    data = '1234567890123456789012345678901234567890'
    #data = '1234567890'
    for run in xrange(runs):
        result = ''
        for i in xrange(repeat):
            result += data
    return result

def str_list(repeat, runs=1):
    data = '1234567890123456789012345678901234567890'
    #data = '1234567890'
    for run in xrange(runs):
        pool = []
        for i in xrange(repeat):
            pool.append(data)
    return ''.join(pool)

def run(func, repeat, runs=1):
    start = time.time()
    x = func(repeat, runs)
    runtime = time.time() - start
    print(len(x))
    return runtime

print run(str_list, 10000)
print run(str_cat, 10000)

print run(str_list, 100, 100)
print run(str_cat, 100, 100)
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

lunar hat geschrieben:@Hyperion: "String.format()" und "System.out.printf()" gibt es auch in Java :)
Jupp. Die hatte ich auch einmal entdeckt, als mir das andere auf den Zeiger ging :-D Dennoch habe ich schon viel Code mit "+" gesehen - daher hab ich das angeführt.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

Die beiden Methoden gibt es gemessen am Alter von Java noch nicht *so* lange. Deshalb vielleicht.
Antworten