Łatwe, ładne drukowanie pływaków w Pythonie?

95

Mam listę pływaków. Jeśli po prostu printto, wygląda to tak:

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

Mógłbym użyć print "%.2f", co wymagałoby forpętli do przejścia przez listę, ale wtedy nie zadziałałoby dla bardziej złożonych struktur danych. Chciałbym coś takiego (całkowicie to zmyślam)

>>> 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
źródło

Odpowiedzi:

24

To stare pytanie, ale dodałbym coś potencjalnie przydatnego:

Wiem, że napisałeś swój przykład na surowych listach Pythona, ale jeśli zdecydujesz się numpyzamiast tego użyć tablic (co byłoby całkowicie uzasadnione w twoim przykładzie, ponieważ wydaje się, że masz do czynienia z tablicami liczb), istnieje (prawie dokładnie) to polecenie, powiedziałeś, że wymyśliłeś:

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

Lub jeszcze lepiej w twoim przypadku, jeśli nadal chcesz widzieć wszystkie dziesiętne naprawdę dokładnych liczb, ale na przykład pozbyć się końcowych zer, użyj ciągu formatującego %g:

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

Aby wydrukować tylko raz i nie zmieniać globalnego zachowania, użyj np.array2stringtych samych argumentów, co powyżej.

PlasmaBinturong
źródło
103

Ponieważ nikt tego nie dodał, należy zauważyć, że od Pythona 2.6+ zalecanym sposobem formatowania ciągów jest formatprzygotowanie się na Python 3+.

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

Nowa składnia formatowania napisów nie jest trudna w użyciu, a mimo to jest dość potężna.

Myślałem, że to może być pprintcoś, ale nic nie znalazłem.

Esteban Küber
źródło
1
To był ten, którego użyłem, ale dodałem, .replace("'", "")aby pozbyć się tych przecinków. str(["{0:0.2f}".format(i) for i in a]).replace("'", "")
Steinarr Hrafn Höskuldsson
Spowoduje to wyświetlenie listy ciągów. Na wydruku każdy element jest ''otoczony. Na przykład, a=[0.2222, 0.3333]będzie produkować ['0.22', '0.33'].
jdhao
Aby usunąć wierzchołek i przecinki, należy użyć' '.join([{0:0.2f}".format(i) for i in a])
Neb
77

Bardziej trwałym rozwiązaniem jest podklasa 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

Problem z podklasami floatpolega na tym, że psuje kod, który wyraźnie szuka typu zmiennej. Ale o ile wiem, to jedyny problem. I proste x = map(float, x)cofnięcie konwersji do prettyfloat.

Niestety, nie możesz po prostu łatać małpy float.__repr__, ponieważ floatjest niezmienna.

Jeśli nie chcesz tworzyć podklas float, ale nie masz nic przeciwko zdefiniowaniu funkcji, map(f, x)jest o wiele bardziej zwięzły niż[f(n) for n in x]

Robert Rossney
źródło
Pomyślałbym, że istnieje prostsze rozwiązanie, ale Twoja odpowiedź jest zdecydowanie najlepsza, ponieważ jesteś chyba jedyną osobą, która faktycznie odpowie na moje pytanie.
static_rtti
4
On jest jedyną osobą, która faktycznie odpowie na twoje -edytowane- pytanie. Nie lekceważąc osoby odpowiadającej, ale nie możesz wyjaśnić pytania, a następnie zlekceważyć resztę odpowiedzi na podstawie informacji, z którymi pracowaliśmy.
Jed Smith
1
Moje pierwotne pytanie wspomniało, że uważam, że pętla for nie jest dobrym rozwiązaniem (dla mnie rozumienie listy jest takie samo, ale zgadzam się, że nie jest jasne). Następnym razem spróbuję wyjaśnić sprawę.
static_rtti
2
[f (n) dla n in x] jest znacznie bardziej pythonowe niż map (f, x).
Robert T. McGibbon
2
Niekoniecznie jestem zwolennikiem tworzenia podklas typu float, ale nie sądzę, aby sprawdzanie typów było prawidłowym argumentem. Podczas sprawdzania typów isinstancenależy używać, a nie równości type(). Gdy jest to zrobione poprawnie, podklasa zmiennej zmiennoprzecinkowej nadal będzie liczona jako zmiennoprzecinkowa.
zondo
37

Możesz to zrobić:

a = [9.0, 0.052999999999999999, 0.032575399999999997, 0.010892799999999999, 0.055702500000000002, 0.079330300000000006]
print ["%0.2f" % i for i in a]
Pablo Santa Cruz
źródło
3
Spowoduje to wydrukowanie ['9.00', '0.05', '0.03', '0.01', '0.06', '0.08'] - w cudzysłowie, których zwykle nie chcesz (wolę mieć poprawną listę liczb zmiennoprzecinkowych wydrukowane)
Emile
23

Zauważ, że możesz również pomnożyć ciąg, np. „% .2f” (przykład: „% .2f” * 10).

>>> print "%.2f "*len(yourlist) % tuple(yourlist)
2.00 33.00 4.42 0.31 
dalloliogm
źródło
3
bardzo elegancko! Podoba mi się
Nathan Fellman
2
-1 okropny hack. Dołącz do sformatowanych fragmentów strun, nie odwrotnie
u0b34a0f6ae
1
więc kaizer.se, czy proponujesz "" .join (["%. 2f"% x dla x na twojej liście]). Muszę wykonać taką konstrukcję w Pythonie.
Gregg Lind,
tak, proponuję, " ".join("%.2f" % x for x in yourlist)ponieważ rozdzielanie ciągów formatujących i wartości interpolacji jest znacznie gorsze niż używanie brzydkiego idiomu Pythona.
u0b34a0f6ae
To ciekawość. Dlaczego krotka działa, gdy lista nie działa? Bez „krotki” popełnia błąd. Czemu?
Joonho Park
8
print "[%s]"%", ".join(map(str,yourlist))

Pozwoli to uniknąć błędów zaokrąglania w reprezentacji binarnej podczas drukowania, bez wprowadzania stałego ograniczenia dokładności (jak formatowanie za pomocą "%.2f"):

[9.0, 0.053, 0.0325754, 0.0108928, 0.0557025, 0.0793303]
fortran
źródło
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))

Wynik:

9.00, 0.05, 0.03, 0.01, 0.06, 0.08
Chikipowpow
źródło
Nie wiem, dlaczego to nie jest wyższe. Rozwiązanie, które nie polega na bibliotekach innych firm!
Fl.pf.
7

Najłatwiejszą opcją powinno być użycie procedury zaokrąglania:

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))

To daje wynik:

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
źródło
to świetna odpowiedź
jjz
6

Aby kontrolować liczbę cyfr znaczących , użyj specyfikatora formatu% g.

Nazwijmy rozwiązanie Emile prettylist2f. Oto zmodyfikowany:

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

Stosowanie:

>>> 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]

Jeśli chcesz mieć elastyczność w liczbie cyfr znaczących, użyj zamiast tego formatowania f-string :

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
źródło
4

Uważam, że Python 3.1 domyślnie wydrukuje je ładniej, bez jakiejkolwiek zmiany kodu. Ale jest to bezużyteczne, jeśli używasz rozszerzeń, które nie zostały zaktualizowane do pracy z Pythonem 3.1

Echo mówi Przywróć Monikę
źródło
1
Python 3.1 wypisze najkrótszą reprezentację dziesiętną, która jest odwzorowywana na tę wartość zmiennoprzecinkową. Na przykład: >>> a, b = float (1.1), float (1.1000000000000001) >>> a 1.1000000000000001 >>> b 1.1000000000000001 >>> print (a, b) 1.1 1.1
Matt Boehm
4

Kompozycje list są twoim przyjacielem.

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

Spróbuj:

>>> 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
źródło
5
Wyrażenie generatora byłoby jeszcze lepsze: "," .join ("%. 2f"% f for f in list_o_numbers)
efotinis
@efotinis Nie dodałem ich jeszcze do mojego repertuaru, ale masz rację - to całkiem sexy.
Jed Smith
1
@Jed: Przeczytaj często zadawane pytania, sekcja „Inne osoby mogą edytować moje rzeczy ?!”: stackoverflow.com/faq . Nie każda edycja jest dobra, ale ta była prawdziwym ulepszeniem. Może potrafisz wymienić obie techniki w swojej odpowiedzi i dodać uwagę na temat różnicy?
Stephan202
3

Możesz użyć pand.

Oto przykład z listą:

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

Jeśli masz dict d i chcesz, aby jego klucze były wierszami:

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

I inny sposób nadania dyktowania DataFrame:

P.DataFrame.from_dict(d, orient='index')
ifmihai
źródło
2

Po pierwsze, elementy wewnątrz kolekcji drukują swój repr. powinieneś dowiedzieć się o __repr__i __str__.

Na tym polega różnica między print repr (1.1) a print 1.1. Połączmy wszystkie te ciągi zamiast reprezentacji:

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
źródło
UWAGA: W Pythonie 2.7 w tym przykładzie wyniki linii „repr” i „str” są identyczne.
ToolmakerSteve
2

Właśnie napotkałem ten problem, próbując użyć pprint do wypisania listy krotek wartości zmiennoprzecinkowych. Zagnieżdżone wyrażenia mogą być złym pomysłem, ale oto co zrobiłem:

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])

Na początku użyłem wyrażeń generatora, ale pprint po prostu zastąpił generator ...

kitsu.eb
źródło
2

Od Pythona 3.6 możesz używać f-stringów:

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

Możesz używać parametrów drukowania, zachowując czytelność kodu:

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

Miałem ten problem, ale żadne z rozwiązań tutaj nie działało dokładnie tak , jak chciałem (chcę, aby wydrukowane dane były prawidłowym wyrażeniem w Pythonie), więc co powiesz na to:

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

Stosowanie:

>>> 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]

(Wiem, że .format () ma być bardziej standardowym rozwiązaniem, ale uważam to za bardziej czytelne)

Emile
źródło
0

Zgadzam się z komentarzem SilentGhost, pętla for nie jest taka zła. Możesz osiągnąć to, co chcesz, dzięki:

l = [9.0, 0.052999999999999999, 0.032575399999999997, 0.010892799999999999, 0.055702500000000002, 0.079330300000000006]
for x in l: print "%0.2f" % (x)
PTBNL
źródło
3
Chociaż pętle for nie są brzydkie, to użycie nie jest strasznie Pythonic.
Jed Smith
-1

Poniższy kod dobrze mi działa.

list = map (lambda x: float('%0.2f' % x), list)
Romerito
źródło