Frage

In Python, das wo und Wann der Verwendung von string-Verkettung versus string-substitution, entzieht sich mir.Wie die string-Verkettung gesehen hat großes steigert die Leistung, ist diese (immer mehr) eine stilistische Entscheidung, sondern als einen praktischen?

Für ein konkretes Beispiel, wie sollte man mit der Konstruktion von flexiblen URIs:

DOMAIN = 'http://stackoverflow.com'
QUESTIONS = '/questions'

def so_question_uri_sub(q_num):
    return "%s%s/%d" % (DOMAIN, QUESTIONS, q_num)

def so_question_uri_cat(q_num):
    return DOMAIN + QUESTIONS + '/' + str(q_num)

Edit:Es wurden auch Vorschläge über die Aufnahme in eine Liste von strings und für die Verwendung von benannten Vertretung.Bei diesen Varianten wird auf das zentrale Thema, die ist, welcher Weg ist der Richtige Weg, es zu tun zu dem Zeitpunkt?Vielen Dank für die Antworten!

War es hilfreich?

Lösung

Verkettung ist (deutlich) schneller laut meiner Maschine.Aber stilistisch, ich bin bereit zu zahlen den Preis der substitution, wenn die Leistung nicht kritisch ist.Naja, und wenn ich die Formatierung, es gibt keine Notwendigkeit, auch die Frage stellen...es gibt keine option, sondern eine interpolation/templating.

>>> import timeit
>>> def so_q_sub(n):
...  return "%s%s/%d" % (DOMAIN, QUESTIONS, n)
...
>>> so_q_sub(1000)
'http://stackoverflow.com/questions/1000'
>>> def so_q_cat(n):
...  return DOMAIN + QUESTIONS + '/' + str(n)
...
>>> so_q_cat(1000)
'http://stackoverflow.com/questions/1000'
>>> t1 = timeit.Timer('so_q_sub(1000)','from __main__ import so_q_sub')
>>> t2 = timeit.Timer('so_q_cat(1000)','from __main__ import so_q_cat')
>>> t1.timeit(number=10000000)
12.166618871951641
>>> t2.timeit(number=10000000)
5.7813972166853773
>>> t1.timeit(number=1)
1.103492206766532e-05
>>> t2.timeit(number=1)
8.5206360154188587e-06

>>> def so_q_tmp(n):
...  return "{d}{q}/{n}".format(d=DOMAIN,q=QUESTIONS,n=n)
...
>>> so_q_tmp(1000)
'http://stackoverflow.com/questions/1000'
>>> t3= timeit.Timer('so_q_tmp(1000)','from __main__ import so_q_tmp')
>>> t3.timeit(number=10000000)
14.564135316080637

>>> def so_q_join(n):
...  return ''.join([DOMAIN,QUESTIONS,'/',str(n)])
...
>>> so_q_join(1000)
'http://stackoverflow.com/questions/1000'
>>> t4= timeit.Timer('so_q_join(1000)','from __main__ import so_q_join')
>>> t4.timeit(number=10000000)
9.4431309007150048

Andere Tipps

Vergessen Sie nicht, über das benannte substitution:

def so_question_uri_namedsub(q_num):
    return "%(domain)s%(questions)s/%(q_num)d" % locals()

Seien Sie vorsichtig bei der Verkettung von strings in einer Schleife! Die Kosten für die string-Verkettung ist proportional zu der Länge des Ergebnisses.Looping führt Sie direkt in das land der N-Quadrat.Einige Sprachen optimieren-Verkettung der zuletzt zugewiesenen string, aber es ist riskant, zu zählen, auf die der compiler für die Optimierung Ihrer quadratischen Algorithmus down "linear".Am besten verwenden Sie die primitive (join?) das dauert eine ganze Liste von strings ist, ist eine einzelne Zuweisung, und verkettet Sie alle in einem gehen.

"Wie die string-Verkettung gesehen hat großes steigert die Leistung..."

Wenn es um performance geht, ist dies gut zu wissen.

Allerdings performance-Probleme, die ich gesehen habe, nie nach unten kommen, um string-Operationen.Ich habe in der Regel bekommen in Schwierigkeiten mit I/O -, Sortier-und O(n2) Vorgänge, die Engpässe.

Bis string-Operationen die performance Limiter, ich werde stick mit Dinge, die offensichtlich sind.Meistens, das ist die substitution, wenn es eine Zeile oder weniger, Verkettung, wenn es Sinn macht und eine Vorlage tool (wie Mako), wenn es groß ist.

Was Sie wollen, zu verketten/zu interpolieren und wie Sie formatieren möchten das Ergebnis sollte Ihre Entscheidung.

  • String-interpolation können Sie ganz einfach formatieren.In der Tat, Ihre string-interpolation-version nicht das gleiche tun wie Ihre Verkettung version;es fügt tatsächlich einen zusätzlichen Schrägstrich vor der q_num parameter.Die gleiche Sache zu tun, würden Sie schreiben return DOMAIN + QUESTIONS + "/" + str(q_num) in diesem Beispiel.

  • Interpolation macht es einfacher, das format numerics; "%d of %d (%2.2f%%)" % (current, total, total/current) wäre viel weniger lesbar in der Verkettung bilden.

  • Verkettung ist nützlich, wenn Sie nicht haben eine Feste Anzahl von items-zu-string-ize.

Auch, wissen Sie, dass Python 2.6 eingeführt, eine neue version der string-interpolation genannt string templating:

def so_question_uri_template(q_num):
    return "{domain}/{questions}/{num}".format(domain=DOMAIN,
                                               questions=QUESTIONS,
                                               num=q_num)

String templating ist geplant, um schließlich ersetzen Sie %-interpolation, aber das wird nicht passieren für eine ganze Weile, denke ich.

Ich war einfach nur testen die Geschwindigkeit von verschiedenen string-Verkettung/substitution Methoden aus Neugier.Eine google-Suche auf das Thema brachte mich hier.Ich dachte, ich würde post meine Ergebnisse in der Hoffnung, dass es helfen könnte, jemanden zu entscheiden.

    import timeit
    def percent_():
            return "test %s, with number %s" % (1,2)

    def format_():
            return "test {}, with number {}".format(1,2)

    def format2_():
            return "test {1}, with number {0}".format(2,1)

    def concat_():
            return "test " + str(1) + ", with number " + str(2)

    def dotimers(func_list):
            # runs a single test for all functions in the list
            for func in func_list:
                    tmr = timeit.Timer(func)
                    res = tmr.timeit()
                    print "test " + func.func_name + ": " + str(res)

    def runtests(func_list, runs=5):
            # runs multiple tests for all functions in the list
            for i in range(runs):
                    print "----------- TEST #" + str(i + 1)
                    dotimers(func_list)

...Nach dem ausführen von runtests((percent_, format_, format2_, concat_), runs=5), Ich fand, dass der % - Methode war etwa doppelt so schnell wie die anderen auf diese kleine strings.Die concat-Methode war immer die langsamste (kaum).Gab es winzig kleine Unterschiede beim Wechsel der Positionen im format() Methode, aber Schaltstellungen war immer mindestens .01 langsamer als die regulären format-Methode.

Probe-test-Ergebnisse:

    test concat_()  : 0.62  (0.61 to 0.63)
    test format_()  : 0.56  (consistently 0.56)
    test format2_() : 0.58  (0.57 to 0.59)
    test percent_() : 0.34  (0.33 to 0.35)

Ich lief, weil ich wollen, verwenden Sie die string-Verkettung in meinen Skripten und ich Frage mich, was der Preis war.Ich lief Sie in verschiedene Aufträge, um sicherzustellen, dass nichts in sich, oder besser Leistung wird das erste oder Letzte.Auf einer seitlichen Anmerkung, ich warf einige mehr string-Generatoren in denen Funktionen wie "%s" + ("a" * 1024) und regelmäßige concat war Sie fast 3 mal so schnell (1.1 vs 2.8) als mit dem format und % Methoden.Ich denke, es hängt auf die Saiten, und was Sie zu erreichen versuchen.Wenn Leistung wirklich zählt, könnte es besser sein, verschiedene Dinge auszuprobieren und zu testen.Ich Neige dazu, wählen Sie Lesbarkeit über Geschwindigkeit, wenn die Geschwindigkeit wird zu einem problem, aber das ist nur mir.SO wusste nicht, wie mein copy/paste, hatte ich, um 8 Leerzeichen auf alles, damit es richtig Aussehen.Normalerweise verwende ich 4.

Denken Sie daran, stilistischen Entscheidungen sind praktische Entscheidungen treffen, wenn Sie jemals plan auf die Aufrechterhaltung oder den code Debuggen :-) Es gibt ein berühmtes Zitat von Knuth (möglicherweise zitieren Hoare?):"Wir sollten nicht vergessen, über kleine Wirkungsgrade, say about 97% der Zeit:vorzeitige Optimierung ist die Wurzel allen übels."

Solange Sie vorsichtig sind, nicht zu (sagen wir) drehen Sie eine O(n) Aufgabe in O(n2) Aufgabe, die ich gehen würde-welche finden Sie am einfachsten zu verstehen..

Ich benutze substitution, wo ich kann.Ich verwende nur die Verkettung, wenn ich Baue einen string in sagen eine for-Schleife.

Eigentlich die richtige Sache zu tun, in diesem Fall (Gebäude, Wege), ist die Verwendung os.path.join.Nicht string-Verkettung oder interpolation

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top