Textersetzung in zwei Steps nicht möglich - warum?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
mimuel
User
Beiträge: 19
Registriert: Montag 8. November 2010, 08:03

Hallo,
ich hab das Phänomen, dass eine Textersetzung von mehreren Platzhaltern nur in einem Stepp möglich ist - nicht in mehreren - warum?

Beispiel:

Old_Text = "das ist ein {text1} zwei Texte {text2}"

so funktioniert es:
New_Text = Old_Text.format(text1='Versuch', text2='abzubilden')

so funktioniert es nicht:
New_Text = Old_Text.format(text1='Versuch')
New_Text = New_Text.format(text2='abzubilden')

Seltsamerweise schmeißt es schon in der ersten Zeile den Fehler "KeyError: 'text2'"

Habt ihr dafür eine Erklärung?
Gruß Michael
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@mimuel: dafür braucht man keine Erklärung. So funktioniert `.format` eben. Wo ist Dein Problem damit?
BlackJack

@mimuel: Die Textersetzung schaut nicht welche Platzhalter ersetzt werden können sondern ersetzt alle Platzhalter mit Werten. Und dazu muss halt auch für jeden Platzhalter ein Wert existieren. Wenn es für einen Platzhalter keinen Wert gibt → Ausnahme.

Warum? Warum nicht? Wenn es anders gelöst worden wäre, dann würde irgendwer fragen warum es keine Ausnahme gibt wenn nicht Werte für alle Platzhalter angegeben werden. So wie es jetzt ist, ist es IMHO sauberer und sinnvoller. Wenn man sich bei einem Platzhalter oder beim Namen für einen Wert vertippt, führt das zu einer Ausnahme. Man kann auch einfacher über Ersetzungen nachdenken/diskutieren bei denen der ersetzte Text wieder etwas enthält was wie Platzhalter aussieht. Und für mehre Ersetzungen müsste man auch beim Escapen von Text der wie Platzhalter aussieht mehr Umstände in Kauf nehmen.
mimuel
User
Beiträge: 19
Registriert: Montag 8. November 2010, 08:03

Hallo,

Danke für Eure Antworten.
In meinem Programm waren die Ersetzungstexte von Bedingungen abhängig.
Jetzt werde ich erst die Erstzungstexte bedingungsabhängig generieren und diese dann alle per format einsetzen.
Hat mich nur verwundert.

Gruß Michael
Benutzeravatar
Kebap
User
Beiträge: 687
Registriert: Dienstag 15. November 2011, 14:20
Wohnort: Dortmund

Man könnte auch mit .replace() arbeiten, falls nicht alle Platzhalter ersetzt werden sollen.
MorgenGrauen: 1 Welt, 8 Rassen, 13 Gilden, >250 Abenteuer, >5000 Waffen & Rüstungen,
>7000 NPC, >16000 Räume, >200 freiwillige Programmierer, nur Text, viel Spaß, seit 1992.
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

man kann auch mit der `Template`-Klasse von Strings arbeiten. Die Methode `safe_substitute` kann auch mit fehlenden Werten umgehen.

Gruß, noisefloor
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Oder man ersetzt Platzhalter mit Platzhaltern:

Code: Alles auswählen

>>> old = 'bla {t1} blub {t2}'
>>> new = old.format(t1='foo', t2='{t2}')
>>> new
'bla foo blub {t2}'
>>> newest = new.format(t2='bar')
>>> newest
'bla foo blub bar'
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Einfach die geschweiften Klammern, bei denen im ersten Schritt keine Ersetzung gemacht werden soll, doppelt schreiben.
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

Und all diese Lösungen haben das Problem, dass in den Parametern keine geschweiften Klammern vorkommen dürfen.

Warum nicht einfach eine Klasse, die sich alles merkt:

Code: Alles auswählen

class FormattingString(object):
    def __init__(self, format_string, *default_args, **default_kw):
        self.format_string = format_string
        self.default_args = default_args
        self.default_kw = default_kw
        self.args = []
        self.kw = {}
 
    def __setitem__(self, key, value):
        self.kw[key] = value
        
    def append(self, value):
        self.args.append(value)
  
    def __str__(self):
        args = self.args + list(self.default_args[len(self.args):])
        kw = dict(self.default_kw, **self.kw)
        return self.format_string.format(*args, **kw)

template = FormattingString("das ist ein {text1} zwei Texte {text2}")
template['text1'] = "Versuch"
template['text2'] = "abzubilden"
print(template)

Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Warum nicht einfach mit Currying?

Code: Alles auswählen

>>> def curry(f=None, *, params=1):
...     def curried(f, *old_args, **old_kwargs):
...         def fun(*new_args, **new_kwargs):
...             args = old_args + new_args
...             kwargs = {}
...             kwargs.update(old_kwargs)
...             kwargs.update(new_kwargs)
...             if len(args) + len(kwargs) < params:
...                 return curried(f, *args, **kwargs)
...             else:
...                 return f(*args, **kwargs)
...         return fun
...     if f is None:
...         return curried
...     else:
...         return curried(f)
... 
>>> old = 'bla {t1} blub {t2}'
>>> format_old = curry(params=2)(old.format)
>>> format_tmp = format_old(t1='foo')
>>> format_tmp(t2='bar')
'bla foo blub bar'
In specifications, Murphy's Law supersedes Ohm's.
Antworten