2016-07-13 7 views
12

sah ich "Why doesn't join() automatically convert its arguments to strings?" und the accepted answer machte mich denken: daWarum ignoriert `str.format()` zusätzliche/unbenutzte Argumente?

Explicit ist besser als implizit.

und

Fehler sollten niemals still passieren.

Warum ignoriert str.format() zusätzliche/nicht verwendete (manchmal versehentlich übergebene) Argumente? Für mich ist es wie ein Fehler aussieht, die lautlos übergeben wird, und es ist sicherlich nicht explizit:

>>> 'abc'.format(21, 3, 'abc', object(), x=5, y=[1, 2, 3]) 
'abc' 

Dies ist eigentlich mein Freund zu einem Problem führen mit os.makedirs(path, exist_ok=True) noch einen Fehler erhöhen, obwohl the docs for os.makedirs() sagte, dass exist_ok=True wird nicht einen Fehler auslösen, auch wenn path bereits existiert. Es stellte sich heraus, dass er nur eine lange Zeile mit verschachtelten Funktionsaufrufen hatte, und die exist_ok wurde an einen verschachtelten .format() Anruf anstelle der os.makedirs() übergeben.

+2

Möchten Sie etwas Einfaches wie: ''{6} {3}'. Format (* range (100))' fail? Oder vielleicht: ''Hallo {Name} Ihre Lieblingsfarbe ist {Farbe}. Format (Name =' Bob ', Farbe =' Blau ', Alter = 21, Planet =' Erde ')' –

+2

@ JonClements Eigentlich ja. Wenn die Saite "Name" und "Farbe" benötigt, glaube ich, dass es ein Fehler ist, sie "Alter" und "Planet" zu übergeben. Wie bereits erwähnt, sollten "Fehler nicht lautlos passieren". Ein Fehler würde auch dazu führen, dass Sie Ihre Aussagen explizit angeben. –

+5

Also, wenn ich ein 'dict' namens' person' habe, das ich herumgereicht habe und einfach eine Zeichenkette basierend auf bestimmten Elementen davon ausdrucken, sollte ich dafür verantwortlich sein ** das ** dict ** zu unterteilen, um zu meiner Formatierung zu passen? Das ist eine wahnsinnige Anforderung - oder glaubst du, dass die Leute wirklich Lust haben, '.format (name = person ['name'], color = ['person'])'? –

Antwort

11

Durch das Ignorieren von nicht verwendeten Argumenten können beliebige Formatzeichenfolgen für Wörterbücher oder Objekte beliebiger Größe erstellt werden.

Angenommen, Sie wollten Ihrem Programm die Möglichkeit geben, den Endbenutzer die Ausgabe ändern zu lassen. Sie dokumentieren, welche Felder verfügbar sind, und weisen Benutzer an, diese Felder in {...} Slots in einer Zeichenfolge zu platzieren. Der Endbenutzer kann dann Templating-Strings mit einer beliebigen Nummer der verwendeten Felder erstellen, einschließlich Null, ohne Fehler.

Mit anderen Worten, die Wahl ist bewusst, weil es praktische Gründe gibt, mehr Argumente zuzulassen als konvertiert werden. Beachten Sie, dass die C# String.Formatter Implementierung, die den Python PEP inspiriert hat, aus denselben Gründen dasselbe tut.

Nicht, dass die Diskussion über diesen Teil der PEP so klar ist; Guido van Rossum an einem gewissen Punkt tries to address this issue:

Der PEP erscheint stumm auf dem, was passiert, wenn es zu wenig oder zu vielen Positionsargumente, oder wenn es fehlt oder nicht verwendete Schlüsselwörter. Fehlende sollten Fehler sein; Ich bin mir nicht sicher über überflüssige (unbenutzte) Einsen. Auf der einen Seite beschwert uns über diese gibt uns mehr Sicherheit , dass die Formatzeichenfolge korrekt ist. Auf der anderen Seite gibt es einige Anwendungsfälle für die Weitergabe von vielen Schlüsselwortparametern (z. B. einfaches Web Templating könnte eine feste Menge von Variablen mit ** dict übergeben). Auch in i18n (Übersetzung) apps ich die Nützlichkeit so dass nicht verwendete Parameter sehen konnte

, an dem der PEP Autor responded, dass sie in diesem Punkt noch unentschlossen waren.

Für Anwendungsfälle, in denen Sie eine Ausnahme für nicht verwendete Argumente auslösen müssen, wird erwartet, dass Sie die string.Formatter() class ableiten und eine Implementierung für Formatter.check_unused_args() bereitstellen; Die Standardimplementierung tut nichts. Dies hilft natürlich nicht Ihrem Freund Fall, wo Sie str.format(*args, **kwargs) statt Formatter().format(str, *args, **kwargs) verwendet haben. Ich glaube, dass bei irgendeinen Punkt die Idee war, dass Sie den von str.format() verwendeten Formatierer mit einer kundenspezifischen Implementierung ersetzen konnten, aber das kam nie zustande.

Wenn Sie die flake8 linter verwenden, dann können Sie die flake8-string-format plugin fügen Sie die offensichtlichen Fälle zu erfassen, in dem Sie in einem expliziten Stichwort Argument übergeben, die von dem Format-String nicht verwendet wird.

+0

Diese Antwort sieht sehr korrekt für mich, downvoters kümmern, um zu erklären, wie es falsch ist? – miradulo

+2

Mit Bezug auf [Ihre Antwort auf die andere Frage, die mich dazu inspirierte, diese Frage zu stellen] (http://stackoverflow.com/questions/22152668/why-doesnt-join-automatisch-convert-its-arguments-to-strings-when -Would-yo/22152693 # 22152693), wie ist dieser Fall anders? Das Verhalten von '.format()' kann Bugs verbergen (wie es bei meinem Freund der Fall war), und '.format()' ignoriert einfach alles, was Sie übergeben. Imo ist es noch schlimmer als das 'Join()' wäre. –

+3

@MarkusMeskanen: Auch im Zen: * Obwohl Praktikabilität Reinheit übertrifft. * Es gibt gute praktische Gründe, hier keine Ausnahme zu machen. Ich stöbere gerade durch die ursprüngliche PEP-Diskussion, um die spezifische Entscheidung dazu zu finden. –