Python: verwendet "..% (var) s .."% local () eine gute Übung?
Entdeckte ich dieses Muster (oder anti-Muster) und ich bin sehr glücklich mit ihm.
Ich empfinde es als sehr Agil:
def example():
age = ...
name = ...
print "hello %(name)s you are %(age)s years old" % locals()
Manchmal benutze ich seine Cousine:
def example2(obj):
print "The file at %(path)s has %(length)s bytes" % obj.__dict__
Brauche ich nicht zu erstellen, die eine künstliche Tupel-und count-Parameter und halten Sie die %s übereinstimmenden Positionen innerhalb des Tupels.
Wie findet Ihr es? Tun/Würden Sie es verwenden? Ja/Nein, erläutern Sie bitte warum.
InformationsquelleAutor der Frage flybywire | 2009-10-11
Du musst angemeldet sein, um einen Kommentar abzugeben.
Es ist OK für kleine Anwendungen und angeblich "one-off" - Skripte, vor allem mit der
vars
Verbesserung erwähnt von @kaizer.se und die.format
version erwähnt von @RedGlyph.Jedoch für große Anwendungen mit einem langen Wartungs Leben und viele Betreuer diese Praxis kann dazu führen, Wartung Kopfschmerzen, und ich denke, da @S. Lott Antwort kommt. Lassen Sie mich erklären, einige der Probleme beteiligt, da Sie möglicherweise nicht offensichtlich sein für diejenigen, die nicht über die Narben von der Entwicklung und Pflege großer Anwendungen (oder wiederverwendbare Komponenten für solche Tiere).
In eine "ernsthafte" Anwendung, Sie würde nicht von Ihrem format-string -, hard-codiert -- oder, wenn Sie hatte, es wäre in irgendeiner form wie
_('Hello {name}.')
wo die_
kommt aus gettext oder ähnliche i18n /L10n-frameworks. Der Punkt ist, dass solch ein Programm (oder wiederverwendbare Module, die passieren können werden verwendet in diesen Anwendungen) muss zur Unterstützung der Internationalisierung (auch als i18n) und locatization (auch bekannt als L10n): Sie möchten, dass Ihre Anwendung in der Lage sein zu emittieren "Hallo Paul" in bestimmten Ländern und Kulturen, "Hallo Paul" in einigen anderen, "Ciao Paul", in anderen noch nicht, und so weiter. So, der format-string wird mehr oder weniger automatisch ersetzt mit einem anderen zur Laufzeit, abhängig von der aktuellen lokalen Einstellungen; statt hardcoded, es lebt in einer Art Datenbank. Für alle Absichten und Zwecke, sich vorstellen, dass format-string immer eine variable, nicht ein string-literal.So, was Sie haben, ist im wesentlichen
ist und Sie kann nicht-trivial genau prüfen was lokalen Namen, die Formatierung ist dabei. Man würde Sie öffnen und Lesen Sie die L10N-Datenbank, identifizieren Sie die format-strings, die hier verwendet werden, verschiedene Einstellungen, überprüfen Sie alle von Ihnen.
So, in der Praxis nicht wissenwas die lokalen Namen sind gehen zu gewöhnen --, die furchtbar crimps die Aufrechterhaltung der Funktion. Sie Wagen es nicht, Sie umzubenennen oder zu entfernen, jede lokale variable, wie es vielleicht schrecklich brechen Sie die Benutzer-Erfahrung für Benutzer, die mit einigen (für Sie) obscure combinaton von Sprache, Gebietsschema und Einstellungen
Wenn Sie haben hervorragende Integrations - /Regressionstests, der Bruch wird gefangen, bevor der beta-Version-aber die QA wird Schreien und Sie wird der release verzögert... und, seien wir ehrlich, während dem Ziel für eine 100% ige Abdeckung mit Einheit tests ist vernünftig, es ist wirklich nicht mit integration tests, sobald man einmal die kombinatorische explosion der Einstellungen [[L10N-und für viele weitere Gründe]] und unterstützten Versionen von allen Abhängigkeiten. Also, Sie nicht nur munter weiter gehen, um zu riskieren, Brüche, weil "Sie werden gefangen werden in QA" (wenn Sie dies tun, können Sie nicht lange in einem Umfeld entwickelt, dass große apps oder wiederverwendbare Komponenten;-).
So, in der Praxis, werden Sie nie entfernen Sie die "name" lokale variable, obwohl der Benutzer Erfahrung, die Leute haben schon lange gewechselt, Gruß zu einem geeigneten "Willkommen, Dread Overlord!" (und entsprechend L10n ' ed Versionen davon). Alles nur, weil Sie ging für
locals()
...Du bist also ansammelnden Reste wegen der Art, Sie haben gekräuselt, Ihre Fähigkeit zu erhalten und zu Bearbeiten Sie Ihre code-und vielleicht, dass "name" lokale variable existiert nur, weil es holte aus einer DB oder ähnliches, so halten Sie (oder andere lokale) etwa ist nicht nur Reste, es ist die Verringerung Ihrer Leistung zu. Ist die Oberfläche Bequemlichkeit
locals()
Wert dass?-)Aber warte, es wird noch schlimmer! Unter den vielen nützlichen Dienstleistungen, die ein
lint
-wie Programm (wie, zum Beispiel, pylint) für Sie tun kann, ist warnen Sie über nicht verwendete lokale Variablen (wünschte, es könnte tun Sie es für nicht verwendete globals auch, aber für wiederverwendbare Komponenten, das ist nur ein bisschen zu hart;-). Auf diese Weise werden Sie fangen die meisten gelegentlichen Rechtschreibfehlern wieif ...: nmae = ...
sehr schnell und kostengünstig, anstatt zu sehen, ein unit-test-Pause und tun sleuth Arbeit zu finden, aus warum es brach (Sie tun zwanghafte, pervasive unit-tests, die würde fangen diese irgendwann, oder?-) -- lint wird Ihnen sagen, über eine nicht verwendete lokale variablenmae
und du wirst sofort zu beheben.Aber wenn Sie in Ihrem code eine
blah.format(**locals())
oder gleich einblah % locals()
... du bist SOL, pal!-) Wie schlecht ist lint zu wissen, obnmae
ist in der Tat eine nicht verwendete variable, oder eigentlich ist es nicht gewöhnt, von was auch immer externe Funktion oder Methode, die Sie übergeben habenlocals()
? Es kann nicht sein-entweder es wird zu warnen, sowieso (was ein "cry wolf" - Effekt, die schließlich führt Sie zu ignorieren oder zu deaktivieren, solche Warnungen), oder es nie zu warnen (mit dem gleichen Ergebnis: keine Warnungen;-).Vergleichen Sie das mit dem "explizit ist besser als implizit" alternative...:
Dort-keine Wartung, - Leistung und-bin-ich-behindert-lint sorgen, gilt nicht mehr, Glückseligkeit! Sie machen es sofort klar ist, alle beteiligten (lint inbegriffen;-) genau was lokale Variablen genutzt werden, und genau für welche Zwecke.
Ich könnte weitermachen, aber ich denke, dieser Beitrag ist schon ziemlich lange;-).
So, Zusammenfassung: "γνῶθι σεαυτόν!" Hmm, ich meine, "erkenne dich selbst!". Und "dich" habe ich eigentlich bedeuten, dass "der Zweck und der Umfang des Codes". Wenn es ein 1-aus-oder-so ungefähr-Ding, nie zu i18n würde und L10n würde, brauchen kaum zukünftige Instandhaltungs -, wird niemals wiederverwendet werden, in einem breiteren Kontext, etc, etc, dann gehen Sie vor und verwenden Sie
locals()
für die kleinen, aber ordentlichen Komfort, wenn Sie sonst wissen, oder auch wenn Sie nicht ganz sicher sind, irren auf der Seite der Vorsicht und machen die Dinge mehr explizit -- leiden die kleinen Unannehmlichkeiten der Rechtschreibung heraus, was genau Sie gehen, und genießen Sie all die daraus resultierenden Vorteile.BTW, dies ist nur eines der Beispiele, wo Python ist bestrebt, die Unterstützung sowohl für "kleine, einmalige, explorative, vielleicht" interaktive Programmierung (durch das zulassen und die Unterstützung riskant Bequemlichkeiten, die sich weit über
locals()
- denkenimport *
eval
exec
und mehrere andere Möglichkeiten, wie Sie können Brei bis namespaces und Risiko, Pflege-Auswirkungen für die Bequemlichkeit), sowie "groß -, wiederverwendbare -, enterprise-y" - apps und-Komponenten. Sie können tun einen ziemlich guten job bei beiden, aber nur, wenn Sie "erkenne dich selbst" und vermeiden Sie die Verwendung von "convenience" - Teile, außer, wenn Sie absolut sicher sind, können Sie tatsächlich leisten können. Mehr als oft nicht, ist entscheidend, "was hat das zu tun, um meine namespaces, und das Bewusstsein für Ihre Bildung und Verwendung durch den compiler, lint &c, den menschlichen Leser und-Betreuer, und so weiter?".Erinnern, "Namespaces sind ein Hupen tolle Idee-lasst uns mehr tun!" ist wie das Zen of Python Schluss... aber Python, als "Sprache für Erwachsene", können Sie definieren die Grenzen, was bedeutet, dass, als Folge der Entwicklung der Umwelt, Ziele und Praktiken. Diese macht nutzen Sie verantwortungsvoll!-)
InformationsquelleAutor der Antwort Alex Martelli
Ich denke, es ist eine große Muster, weil Sie Nutzung von built-in-Funktionalität reduzieren den code, den Sie schreiben müssen. Ich persönlich finde es ganz Pythonic.
Ich nie code schreiben, brauche ich nicht zu schreiben - weniger code ist besser als mehr code, und diese Praxis der Verwendung von
locals()
zum Beispiel erlaubt es mir, weniger code zu schreiben und ist auch sehr einfach zu Lesen und zu verstehen.InformationsquelleAutor der Antwort Andrew Hare
Nie in einer million Jahren. Es ist unklar, was den Kontext für die Formatierung:
locals
konnte beinhalten fast alle Variablen.self.__dict__
ist nicht so vage. Perfekt schrecklich zu verlassen, zukünftige Entwickler kratzen Ihre Köpfe über das, was die Gemeinden und was nicht vor Ort.Es ist eine absichtliche Geheimnis. Warum satteln Sie Ihr Unternehmen mit Zukunft Wartung Kopfschmerzen, wie?
InformationsquelleAutor der Antwort S.Lott
Bezüglich der "Vetter" statt
obj.__dict__
es sieht viel besser aus mit den neuen string-Formatierung:Ich verwende es oft für repr Methoden, z.B.
InformationsquelleAutor der Antwort pfctdayelise
Den
"%(name)s" % <dictionary>
oder noch besser, die"{name}".format(<parameters>)
das Verdienst zu,Ich würde dazu neigen, zu Gunsten der str.format(), da sollte es die Art und Weise zu tun, dass in Python 3 (pro PEP 3101), und ist bereits von 2.6. Mit
locals()
obwohl Sie haben würde, um dies zu tun:InformationsquelleAutor der Antwort RedGlyph
Mithilfe der integrierten
vars([object])
(Dokumentation) vielleicht machen die zweiten sehen Sie besser aus:Ist der Effekt natürlich genau das gleiche.
InformationsquelleAutor der Antwort u0b34a0f6ae
Gibt es nun einen offiziellen Weg, dies zu tun, wie der Python-3.6.0: formatierte string-Literale.
Funktioniert es so:
E. g. statt diese:
nur dazu:
Hier ist das offizielle Beispiel:
Referenz:
InformationsquelleAutor der Antwort P1h3r1e3d13