Einfaches hübsches Drucken von Floats in Python?

93

Ich habe eine Liste von Schwimmern. Wenn ich es einfach printmache, zeigt es sich so:

[9.0, 0.052999999999999999, 0.032575399999999997, 0.010892799999999999, 0.055702500000000002, 0.079330300000000006]

Ich könnte verwenden print "%.2f", was eine forSchleife erfordern würde , um die Liste zu durchlaufen, aber dann würde es für komplexere Datenstrukturen nicht funktionieren. Ich hätte gerne so etwas wie (ich mache das komplett nach)

>>> import print_options
>>> print_options.set_float_precision(2)
>>> print [9.0, 0.052999999999999999, 0.032575399999999997, 0.010892799999999999, 0.055702500000000002, 0.079330300000000006]
[9.0, 0.05, 0.03, 0.01, 0.06, 0.08]
static_rtti
quelle

Antworten:

23

Es ist eine alte Frage, aber ich möchte etwas potenziell Nützliches hinzufügen:

Ich weiß, dass Sie Ihr Beispiel in rohen Python-Listen geschrieben haben, aber wenn Sie sich numpystattdessen für die Verwendung von Arrays entscheiden (was in Ihrem Beispiel absolut legitim wäre, weil Sie sich anscheinend mit Arrays von Zahlen befassen), gibt es (fast genau) diesen Befehl sagte du hast erfunden:

import numpy as np
np.set_printoptions(precision=2)

Oder noch besser in Ihrem Fall, wenn Sie immer noch alle Dezimalstellen wirklich präziser Zahlen sehen möchten, aber nachfolgende Nullen entfernen möchten, verwenden Sie beispielsweise die Formatierungszeichenfolge %g:

np.set_printoptions(formatter={"float_kind": lambda x: "%g" % x})

Verwenden Sie np.array2stringdieselben Argumente wie oben , um nur einmal zu drucken und das globale Verhalten nicht zu ändern .

PlasmaBinturong
quelle
101

Wie noch niemand hinzugefügt hat, sollte beachtet werden, dass ab Python 2.6+ die empfohlene Methode zum Formatieren von Zeichenfolgen darin besteht format, sich auf Python 3+ vorzubereiten .

print ["{0:0.2f}".format(i) for i in a]

Die neue Syntax zur Formatierung von Zeichenfolgen ist nicht schwer zu verwenden und dennoch recht leistungsfähig.

Ich dachte, das pprintkönnte etwas haben, aber ich habe nichts gefunden.

Esteban Küber
quelle
1
Dies war die, die ich verwendet habe, aber ich habe hinzugefügt .replace("'", ""), um diese Kommas zu entfernen. str(["{0:0.2f}".format(i) for i in a]).replace("'", "")
Steinarr Hrafn Höskuldsson
Dies erzeugt eine Liste von Zeichenfolgen. In der gedruckten Ausgabe hat jedes Element ''um sich herum. Zum Beispiel a=[0.2222, 0.3333]wird es produzieren ['0.22', '0.33'].
JDHAO
Um den Scheitelpunkt und die Kommas zu entfernen, sollten Sie' '.join([{0:0.2f}".format(i) for i in a])
Neb
78

Eine dauerhaftere Lösung ist die Unterklasse float:

>>> class prettyfloat(float):
    def __repr__(self):
        return "%0.2f" % self

>>> x
[1.290192, 3.0002, 22.119199999999999, 3.4110999999999998]
>>> x = map(prettyfloat, x)
>>> x
[1.29, 3.00, 22.12, 3.41]
>>> y = x[2]
>>> y
22.12

Das Problem bei der Unterklasse floatbesteht darin, dass Code unterbrochen wird, der explizit nach dem Typ einer Variablen sucht. Aber soweit ich das beurteilen kann, ist das das einzige Problem. Und ein einfaches x = map(float, x)macht die Konvertierung zu rückgängig prettyfloat.

Tragischerweise kann man nicht einfach Affenpflaster machen float.__repr__, weil es floatunveränderlich ist.

Wenn Sie keine Unterklasse erstellen möchten float, aber nichts dagegen haben, eine Funktion zu definieren, map(f, x)ist dies viel prägnanter als[f(n) for n in x]

Robert Rossney
quelle
Ich hätte gedacht, es gäbe eine einfachere Lösung, aber Ihre Antwort ist eindeutig die beste, da Sie ungefähr die einzige sind, die meine Frage tatsächlich beantwortet.
static_rtti
4
Er ist der einzige, der Ihre bearbeitete Frage tatsächlich beantwortet. Den Antwortenden nicht herabsetzen, aber Sie können eine Frage nicht klären und dann den Rest der Antwortenden anhand der Informationen, mit denen wir gearbeitet haben, abwerten.
Jed Smith
1
In meiner ursprünglichen Frage wurde erwähnt, dass ich eine for-Schleife für keine gute Lösung hielt (für mich ist das Listenverständnis dasselbe, aber ich stimme zu, dass dies nicht klar war). Ich werde versuchen, das nächste Mal klarer zu sein.
static_rtti
2
[f (n) für n in x] ist viel pythonischer als map (f, x).
Robert T. McGibbon
2
Ich bin nicht unbedingt für eine Unterklasse von float, aber ich denke nicht, dass die Typprüfung ein gültiges Argument ist. Bei der Prüfung von Typen isinstancesollte nicht Gleichheit von verwendet werden type(). Wenn es richtig gemacht wird, wird eine Unterklasse von float immer noch als float gezählt.
Zondo
37

Du kannst tun:

a = [9.0, 0.052999999999999999, 0.032575399999999997, 0.010892799999999999, 0.055702500000000002, 0.079330300000000006]
print ["%0.2f" % i for i in a]
Pablo Santa Cruz
quelle
3
Dadurch wird ['9.00', '0.05', '0.03', '0.01', '0.06', '0.08'] gedruckt - mit Anführungszeichen, die Sie normalerweise nicht möchten (ich bevorzuge eine gültige Liste von Floats gedruckt)
Emile
23

Beachten Sie, dass Sie auch eine Zeichenfolge wie "% .2f" multiplizieren können (Beispiel: "% .2f" * 10).

>>> print "%.2f "*len(yourlist) % tuple(yourlist)
2.00 33.00 4.42 0.31 
dalloliogm
quelle
3
sehr elegant! Ich mag es
Nathan Fellman
2
-1 schrecklicher Hack. Verbinden Sie formatierte Saitenstücke, bitte nicht anders herum
u0b34a0f6ae
1
also kaizer.se, schlagen Sie "" .join vor (["%. 2f"% x für x in Ihrer Liste]). Ich muss diese Art von Konstruktion in Python machen.
Gregg Lind
Ja, ich schlage vor, " ".join("%.2f" % x for x in yourlist)da das Trennen von Zeichenfolgen und Interpolationswerten im Format viel schlechter ist als die Verwendung einer hässlichen Python-Sprache.
u0b34a0f6ae
Es ist Neugier. Warum funktioniert Tupel, während die Liste fehlschlägt? Ohne "Tupel" macht es Fehler. Warum?
Joonho Park
8
print "[%s]"%", ".join(map(str,yourlist))

Dadurch werden Rundungsfehler in der Binärdarstellung beim Drucken vermieden, ohne dass eine feste Genauigkeitsbeschränkung eingeführt wird (wie beim Formatieren mit "%.2f"):

[9.0, 0.053, 0.0325754, 0.0108928, 0.0557025, 0.0793303]
fortran
quelle
7
l = [9.0, 0.052999999999999999, 0.032575399999999997, 0.010892799999999999, 0.055702500000000002, 0.079330300000000006]

Python 2:

print ', '.join('{:0.2f}'.format(i) for i in l)

Python 3:

print(', '.join('{:0.2f}'.format(i) for i in l))

Ausgabe:

9.00, 0.05, 0.03, 0.01, 0.06, 0.08
Chikipowpow
quelle
Ich weiß nicht, warum das nicht höher ist. Eine Lösung, die nicht auf Bibliotheken von Drittanbietern basiert!
Fl.pf.
7

Die einfachste Option sollte die Verwendung einer Rundungsroutine sein:

import numpy as np
x=[9.0, 0.052999999999999999, 0.032575399999999997, 0.010892799999999999, 0.055702500000000002, 0.079330300000000006]

print('standard:')
print(x)
print("\nhuman readable:")
print(np.around(x,decimals=2))

Dies erzeugt die Ausgabe:

standard:
[9.0, 0.053, 0.0325754, 0.0108928, 0.0557025, 0.0793303]

human readable:
[ 9.    0.05  0.03  0.01  0.06  0.08]
Markus Dutschke
quelle
Dies ist eine großartige Antwort
jjz
4

Ich glaube, dass Python 3.1 sie standardmäßig besser druckt, ohne dass sich der Code ändert. Dies ist jedoch nutzlos, wenn Sie Erweiterungen verwenden, die nicht für Python 3.1 aktualisiert wurden

Echo sagt Reinstate Monica
quelle
1
Python 3.1 druckt die kürzeste Dezimaldarstellung, die diesem Gleitkommawert zugeordnet ist. Zum Beispiel: >>> a, b = float (1.1), float (1.1000000000000001) >>> a 1.1000000000000001 >>> b 1.1000000000000001 >>> print (a, b) 1.1 1.1
Matt Boehm
4

List Comps sind dein Freund.

print ", ".join("%.2f" % f for f in list_o_numbers)

Versuch es:

>>> nums = [9.0, 0.052999999999999999, 0.032575399999999997, 0.010892799999999999]
>>> print ", ".join("%.2f" % f for f in nums)
9.00, 0.05, 0.03, 0.01
Jed Smith
quelle
5
Ein Generatorausdruck wäre noch besser: "," .join ("%. 2f"% f für f in list_o_numbers)
efotinis
@efotinis Habe diese noch nicht in mein Repertoire aufgenommen, aber du hast recht - das ist ziemlich sexy.
Jed Smith
1
@Jed: Bitte lesen Sie die FAQ, Abschnitt "Andere Leute können meine Sachen bearbeiten ?! ": Stackoverflow.com/faq . Nicht jede Bearbeitung ist gut, aber diese war eine echte Verbesserung. Vielleicht können Sie beide Techniken in Ihrer Antwort auflisten und einen Hinweis zum Unterschied hinzufügen?
Stephan202
4

Verwenden Sie den Formatbezeichner% g, um die Anzahl der signifikanten Stellen zu steuern .

Nennen wir Emiles Lösung prettylist2f. Hier ist die modifizierte:

prettylist2g = lambda l : '[%s]' % ', '.join("%.2g" % x for x in l)

Verwendung:

>>> c_e_alpha_eps0 = [299792458., 2.718281828, 0.00729735, 8.8541878e-12]
>>> print(prettylist2f(c_e_alpha_eps0)) # [299792458.00, 2.72, 0.01, 0.00]
>>> print(prettylist2g(c_e_alpha_eps0)) # [3e+08, 2.7, 0.0073, 8.9e-12]

Wenn Sie Flexibilität bei der Anzahl der signifikanten Stellen wünschen, verwenden Sie stattdessen die Formatierung der F-Zeichenfolge :

prettyflexlist = lambda p, l : '[%s]' % ', '.join(f"{x:.{p}}" for x in l)
print(prettyflexlist(3,c_e_alpha_eps0)) # [3e+08, 2.72, 0.0073, 8.85e-12]
Rainald62
quelle
3

Sie könnten Pandas verwenden.

Hier ist ein Beispiel mit einer Liste:

In: import pandas as P
In: P.set_option('display.precision',3)
In: L = [3.4534534, 2.1232131, 6.231212, 6.3423423, 9.342342423]
In: P.Series(data=L)
Out: 
0    3.45
1    2.12
2    6.23
3    6.34
4    9.34
dtype: float64

Wenn Sie ein Diktat d haben und dessen Schlüssel als Zeilen möchten:

In: d
Out: {1: 0.453523, 2: 2.35423234234, 3: 3.423432432, 4: 4.132312312}

In: P.DataFrame(index=d.keys(), data=d.values())
Out:  
    0
1   0.45
2   2.35
3   3.42
4   4.13

Und eine andere Möglichkeit, einem DataFrame ein Diktat zu geben:

P.DataFrame.from_dict(d, orient='index')
ifmihai
quelle
2

Erstens drucken Elemente in einer Sammlung ihre Repräsentanten. Sie sollten über __repr__und lernen __str__.

Dies ist der Unterschied zwischen print repr (1.1) und print 1.1. Verbinden wir alle diese Zeichenfolgen anstelle der Darstellungen:

numbers = [9.0, 0.053, 0.0325754, 0.0108928, 0.0557025, 0.07933]
print "repr:", " ".join(repr(n) for n in numbers)
print "str:", " ".join(str(n) for n in numbers)
u0b34a0f6ae
quelle
HINWEIS: In Python 2.7 sind in diesem Beispiel die Ergebnisse der Zeile "repr" und der Zeile "str" ​​identisch.
ToolmakerSteve
2

Ich bin gerade auf dieses Problem gestoßen, als ich versucht habe, mit pprint eine Liste von Tupeln von Floats auszugeben. Verschachtelte Verständnisse mögen eine schlechte Idee sein, aber ich habe Folgendes getan:

tups = [
        (12.0, 9.75, 23.54),
        (12.5, 2.6, 13.85),
        (14.77, 3.56, 23.23),
        (12.0, 5.5, 23.5)
       ]
pprint([['{0:0.02f}'.format(num) for num in tup] for tup in tups])

Ich habe zuerst Generatorausdrücke verwendet, aber pprint hat den Generator nur wiederholt ...

kitsu.eb
quelle
2

Ab Python 3.6 können Sie F-Strings verwenden:

list_ = [9.0, 0.052999999999999999, 
         0.032575399999999997, 0.010892799999999999, 
         0.055702500000000002, 0.079330300000000006]

print(*[f"{element:.2f}" for element in list_])
#9.00 0.05 0.03 0.01 0.06 0.08

Sie können Druckparameter verwenden, während der Code gut lesbar bleibt:

print(*[f"{element:.2f}" for element in list_], sep='|', end='<--')
#9.00|0.05|0.03|0.01|0.06|0.08<--
x0s
quelle
1

Ich hatte dieses Problem, aber keine der Lösungen hier hat genau das getan , was ich wollte (ich möchte, dass die gedruckte Ausgabe ein gültiger Python-Ausdruck ist). Wie wäre es also damit:

prettylist = lambda l : '[%s]' % ', '.join("%.2f" % f for f in l)

Verwendung:

>>> ugly = [9.0, 0.052999999999999999, 0.032575399999999997,
            0.010892799999999999, 0.055702500000000002, 0.079330300000000006]
>>> prettylist = lambda l : '[%s]' % ', '.join("%.2f" % f for f in l)
>>> print prettylist(ugly)
[9.00, 0.05, 0.03, 0.01, 0.06, 0.08]

(Ich weiß, dass .format () die Standardlösung sein soll, aber ich finde dies besser lesbar.)

Emile
quelle
0

Ich stimme dem Kommentar von SilentGhost zu, die for-Schleife ist nicht so schlecht. Sie können erreichen, was Sie wollen mit:

l = [9.0, 0.052999999999999999, 0.032575399999999997, 0.010892799999999999, 0.055702500000000002, 0.079330300000000006]
for x in l: print "%0.2f" % (x)
PTBNL
quelle
3
Während for-Schleifen nicht hässlich sind, ist diese Verwendung nicht besonders pythonisch.
Jed Smith
-1

Der folgende Code funktioniert gut für mich.

list = map (lambda x: float('%0.2f' % x), list)
Romerito
quelle