ubuntuusers.de

[Python] Tausendertrennzeichen

Status: Ungelöst | Ubuntu-Version: Nicht spezifiziert
Antworten |

Ferio Team-Icon

Avatar von Ferio

Anmeldungsdatum:
24. April 2007

Beiträge: 383

Weiß jemand, wie man das Tausendertrennzeichen für das locale-Modul setzt? Das Problem ist, dass "thousands_sep" bei mir bei "de_DE" leer ist.

In [1]: import locale

In [2]: locale.setlocale(locale.LC_NUMERIC, '')

Out[2]: 'de_DE.UTF-8'

In [3]: locale.format("%d", 123456, grouping=True)

Out[3]: '123456'  

In [4]: locale.localeconv()

Out[4]: 
{'currency_symbol': '',
 'decimal_point': ',',
 'frac_digits': 127,
 'grouping': [127],
 'int_curr_symbol': '',
 'int_frac_digits': 127,
 'mon_decimal_point': '',
 'mon_grouping': [],
 'mon_thousands_sep': '',
 'n_cs_precedes': 127,
 'n_sep_by_space': 127,
 'n_sign_posn': 127,
 'negative_sign': '',
 'p_cs_precedes': 127,
 'p_sep_by_space': 127,
 'p_sign_posn': 127,
 'positive_sign': '',
 'thousands_sep': ''}

EnTeQuAk Team-Icon

Avatar von EnTeQuAk

Anmeldungsdatum:
17. Mai 2006

Beiträge: 3289

Vielleicht solltest du statt '' einfach mal ne richtige Sprache angeben:

In [1]: import locale

In [2]: locale.setlocale(locale.LC_NUMERIC, 'german')
Out[2]: 'german'

In [3]: locale.format('%.2f', 2134.98, grouping=True)
Out[3]: '2.134,98'

Wobei ich sagen muss, das bei mir es auch ohne Sprachangabe geht (englische locale).

Gruß, Christopher.

Ferio Team-Icon

(Themenstarter)
Avatar von Ferio

Anmeldungsdatum:
24. April 2007

Beiträge: 383

„german“ gibt es bei mir nicht. Das Problem ist, dass das Tausendertrennzeichen bei den deutschsprachigen Sachen irgendwie fehlt, auch schon auf Betriebssystemebene. Ich hatte gehofft, dass man das auch irgendwie überschreiben kann.

EnTeQuAk Team-Icon

Avatar von EnTeQuAk

Anmeldungsdatum:
17. Mai 2006

Beiträge: 3289

Ferio schrieb:

„german“ gibt es bei mir nicht. Ich habe das Problem ist, dass das Tausendertrennzeichen bei den deutschsprachigen Sachen irgendwie fehlt, auch schon auf Betriebssystemebene. Ich hatte gehofft, dass man das auch irgendwie überschreiben kann.

Du kannst auch einfach das ganze als Funktion nehmen:

1
2
3
4
5
6
7
8
9
from itertools import cycle

def format_int(i, sep='.'):
    cyc = cycle(['', '', sep])
    s = str(i)
    last = len(s) - 1
    formatted = [(cyc.next() if idx != last else '') + char
                 for idx, char in enumerate(reversed(s))]
    return ''.join(reversed(formatted))

Aber schön ist anders.

Gruß, Christopher.

snafu1

Avatar von snafu1

Anmeldungsdatum:
5. September 2007

Beiträge: 2133

Wohnort: Gelsenkirchen

@EnTeQuAk:

Ich glaube es geht eher um's Anzeige-/Eingabeformat als darum, tatsächlich mit einer umgewandelten Zahl zu arbeiten, die dann auch noch ein String ist.

EnTeQuAk Team-Icon

Avatar von EnTeQuAk

Anmeldungsdatum:
17. Mai 2006

Beiträge: 3289

snafu1 schrieb:

@EnTeQuAk:

Ich glaube es geht eher um's Anzeige-/Eingabeformat als darum, tatsächlich mit einer umgewandelten Zahl zu arbeiten, die dann auch noch ein String ist.

Ist mir schon klar. Deshalb ist und bleibt locale.format der richtige Weg. Das ganze scheint nen Bug in Ferios MacOSX zu sein (haben wir schon im IRC geklärt).

Gruß, Christopher

snafu1

Avatar von snafu1

Anmeldungsdatum:
5. September 2007

Beiträge: 2133

Wohnort: Gelsenkirchen

Wenn man das eine Weile nutzen möchte, könnte man sich ja eine Klasse schreiben:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
In [37]: class GermanInt(int):
    def __init__(self, integer):
        self.integer = integer
    def __str__(self):
        return locale.format('%d', self.integer, grouping=True)
   ....:     
   ....:     

In [42]: int = GermanInt

In [43]: int(1234567)
Out[43]: 1.234.567

Sauberer wäre es natürlich, eine Umgebungsvariable zu nutzen, falls es in Python dafür eine gibt.

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4674

Wohnort: Berlin

@snafu1: Was soll denn diese sinnfreie Klasse bringen? Der Name stimmt ja schonmal nicht, weil Du einfach locale.format() verwendest. Das bringt zum Beispiel bei amerikanischen "Locales" ganz bestimmt keine Ausgabe, die man in Deutschland erwarten würde. Oder bei Schweizern, oder…

snafu1

Avatar von snafu1

Anmeldungsdatum:
5. September 2007

Beiträge: 2133

Wohnort: Gelsenkirchen

Das war jetzt nur ein Beispiel. Das Setzen der deutschen Locales gehört natürlich in __init__().

Vielleicht möchte man das ganze auch IntFormatter oder PrettyInt nennen, um die anzuwendenen Locales frei wählen zu können. Außerdem müssen für Rechenoperationen wahrscheinlich auch noch ein paar Klassen überschrieben werden. Jedenfalls ergibt eine Addition von zwei angepassten int-Klassen wieder ein Ergebnis ohne Trennzeichen.

Ich wollte damit eigentlich eher zeigen, dass man in dem Fall IMHO besser eine Klasse als eine Funktion verwendet, da man sich zu Nutze machen kann, dass int's in Python eben auch Klassen sind. Denn wie in meinem ersten Beitrag angesprochen, möchte man ja meist nur eine Trennzeichen-Repräsentation anzeigen, intern aber weiter mit "normalen" int's arbeiten.

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4674

Wohnort: Berlin

Das setzen einer Locale gehört ganz bestimmt nicht in die __init__() von so einer Klasse! Das ist eine globale Einstellung, die das Verhalten von allen möglich anderen Komponenten eines Programms verändern kann. Da können dann an ganz anderer Stelle Sachen bei "kaputt" gehen oder plötzlich anders aussehen als erwartet. Selbst wenn man nur in der __str__ auf die gewünschte Locale umschaltet und vor der Rückgabe des formatierten Wertes wieder auf den ursprünglichen Wert zurück schaltet, hat man Programme die an dieser Stelle ziemlich global nicht "thread safe" sind.

Eine von int abgeleitete Klasse nur um die Ausgabe zu modifizieren ist nicht wirklich praxistauglich. Man muss dann alle Rechenoperationen neu implementieren, damit die kein normales int zurück geben. Und das alles nur, weil man an, verglichen an der Anzahl der Rechenoperationen, wenigen Stellen gerne eine Anzeige mit Tausendertrennzeichen hätte. An genau diesen Stellen könnte man aber auch einfach eine Funktion aufrufen, welche die entsprechende Formatierung als Zeichenkette vornimmt.

Und wie geht man beim Ableiten von int mit der automatischen Konvertierung in long um, wenn ein Überlauf auftritt?

Antworten |