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

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.


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.


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]


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]

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 

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]

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

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]

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]

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


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

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

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)

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


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

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)


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)

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)
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.