2012-06-04 7 views
28

Ich vor kurzem (endlich?) Begann zu verwenden .format() und haben eine vielleicht ein wenig obskure Frage darüber.Verwenden von .format() zum Formatieren einer Liste mit Feldbreite Argumente

Bei

res = ['Irene Adler', 35, 24.798] 

und

(1) print('{0[0]:10s} {0[1]:5d} {0[2]:.2f}'.format(res)) 
(2) print('{:{}s} {:{}d} {:{}f}'.format(res[0], 10, res[1], 5, res[2], .2)) 

Arbeit groß und beide Druck:

Irene Adler 35 24.80 
Irene Adler 35 24.80 

Ich wusste nicht, dass ich mit Listen wie in (1) beschäftigen könnte die ist sauber. I hatte über Feldbreite Argumente (2) mit der alten % Formatierung zuvor gesehen.

Meine Frage ist, über den Wunsch, so etwas zu tun, die kombiniert (1) und (2):

(3) print('{0[0]:{}s} {0[1]:{}d} {0[2]:{}f}'.format(res, 10, 5, .2)) 

Allerdings bin ich nicht in der Lage, dies zu tun, und ich habe nicht in der Lage gewesen, um herauszufinden, aus der Dokumentation, wenn das überhaupt möglich ist. Es wäre schön, nur die Liste zu drucken, und die Argumente für die Breite zu liefern.

By the way, ich habe auch versucht, diese (w/o Glück):

args = (10, 5, .2) 
(4) print('{0[0]:{}s} {0[1]:{}d} {0[2]:{}f}'.format(res, args)) 

In beiden Fällen bekam ich:

D:\Users\blabla\Desktop>python tmp.py 
Traceback (most recent call last): 
    File "tmp.py", line 27, in <module> 
    print('{0[0]:{}s} {0[1]:{}d} {0[2]:{}f}'.format(res, 10, 5, .2)) 
ValueError: cannot switch from manual field specification to automatic field numbering 

D:\Users\blabla\Desktop>python tmp.py 
Traceback (most recent call last): 
    File "tmp.py", line 35, in <module> 
    print('{0[0]:{}s} {0[1]:{}d} {0[2]:{}f}'.format(res, args)) 
ValueError: cannot switch from manual field specification to automatic field numbering 

Ich habe auch versucht zip() mit den beiden Sequenzen zu kombinieren, ohne Glück.

Meine Frage ist:

Kann ich eine Liste angeben gedruckt werden effektiv zu tun, was ich versuchte erfolglos in (3) zu tun, und (4) (klar, ob dies möglich ist, ich bin nicht die richtige Syntax verwenden) und wenn ja, wie?

Antwort

43

Die Fehlermeldung

ValueError: cannot switch from manual field specification to automatic field numbering 

ziemlich sagt alles: Sie müssen expliziten Feldindizes everwhere geben, und

print('{0[0]:{1}s} {0[1]:{2}d} {0[2]:{3}f}'.format(res, 10, 5, .2)) 

funktioniert gut.

+3

Danke Sven, nicht sicher, warum ich das nicht bekommen habe. Ich habe auch herausgefunden, dass ich das tun kann: 'args = (10, 5, .2)' und dann 'print ('{0 [0]: {1} s} {0 [1]: {2} d} { 0 [2]: {3} f} '. Format (res, * args)) '.. sehr schön. – Levon

2

Wenn Sie .format(res, args) verwenden möchten, können Sie alle Indizes im Formatstring wie die angeben:

>>> print('{0[0]:{1[0]}s} {0[1]:{1[1]}d} {0[2]:{1[2]}f}'.format(res, args)) 
Irene Adler 35 24.80 

Aber, wenn Sie die Formatzeichenfolge ohne Indizes machen möchten, können Sie ein Tupel von aufeinanderfolgenden erstellen Paare (res[0], args[0], ... , res[-1], args[-1]).

Dies wird durch dieses Idiom getan:

>>> sum(zip(res, args),()) 
('Irene Adler', 10, 35, 5, 24.798, 0.2) 

Sie können nun diese in einem vereinfachten Format-String übergeben (über * -Argument):

>>> fmt = sum(zip(res, args),()) 
>>> print('{:{}s} {:{}d} {:{}f}'.format(*fmt)) 
('Irene Adler', 10, 35, 5, 24.798, 0.2) 

Dies kann natürlich geschehen in einer Zeile:

>>> print('{:{}s} {:{}d} {:{}f}'.format(*sum(zip(res, args),()))) 
Irene Adler 35 24.80 

Um es lesbar zu machen, würde ich die Transformation nennen :

def flat_pairs(iterable1, iterable2): 
    return sum(zip(iterable1, iterable2),()) 

# (...) 

>>> print('{:{}s} {:{}d} {:{}f}'.format(*flat_pairs(res, args))) 
Irene Adler 35 24.80 

denke ich, die letzten ein vernünftiger Kompromiss zwischen Lesbarkeit ist, Bequemlichkeit und natürlich - Ihre Pythonic Denkweise vorführt, die für das Spiel mit solchen Sachen die primäre Motivation ist.

Verwandte Themen