2014-12-31 1 views
9

einen Formatierungsstring Gegeben:Wie kann ich die Liste der in einer Formatierungszeichenfolge verwendeten Namen abrufen?

x = "hello %(foo)s there %(bar)s" 

Gibt es eine Möglichkeit, die Namen der Formatierung Variablen zu bekommen? (Ohne sie direkt zu analysieren).

Mit einem Regex wäre nicht zu hart, aber ich frage mich, ob es einen direkteren Weg, um diese zu bekommen.

+5

Es ist [sehr einfach] (https://docs.python.org/2/library/string.html#string.Formatter), wenn Sie zur neuen Formatvorlage wechseln können. –

+0

nicht wirklich eine Option, leider – qhfgva

Antwort

7

Verwenden Sie eine dict Unterklasse mit überschriebene __missing__ Methode und von dort können Sie alle fehlenden Formatvariablen sammeln:

class StringFormatVarsCollector(dict): 
    def __init__(self, *args, **kwargs): 
     self.format_vars = [] 

    def __missing__(self, k): 
     self.format_vars.append(k) 
...   
def get_format_vars(s): 
    d = StringFormatVarsCollector()  
    s % d      
    return d.format_vars 
... 
>>> get_format_vars("hello %(foo)s there %(bar)s") 
['foo', 'bar'] 
+0

FWIW, das ist die Methode, die ich gewählt habe. – qhfgva

3

Die Formatfelder sind nur für den Operator % relevant, nicht für die Zeichenfolge selbst. Es gibt also kein Attribut wie str.__format_fields__, auf das Sie zugreifen können, um die Feldnamen zu erhalten.

Ich würde sagen, dass die Verwendung von Regex in diesem Fall eigentlich der richtige Ansatz ist. Sie können re.findall leicht die Namen zu extrahieren:

>>> import re 
>>> x = "hello %(foo)s there %(bar)s" 
>>> re.findall('(?<!%)%\(([^)]+)\)[diouxXeEfFgGcrs]', x) 
['foo', 'bar'] 
>>> 

Im Folgenden finden Sie eine Erklärung der Muster:

(?<!%)    # Negated look-behind to make sure that we do not match %% 
%     # Matches % 
\(    # Matches (
(     # Starts a capture group 
[^)]+    # Matches one or more characters that are not) 
)     # Closes the capture group 
\)     # Matches) 
[diouxXeEfFgGcrs] # Matches one of the characters in the square brackets 
+0

Ich würde auch nach der schließenden Klammer nach einem der gültigen Formatierungszeichen suchen; '[diouxXeEfFgGcrs]' sollte tun. –

+0

Dort denke ich, habe ich alle Knicke gebügelt. :) – iCodez

+0

Was ist mit '" hallo %%% (foo) "'? – Kobi

5

Wenn Sie möchten die Zeichenfolge nicht analysieren, können Sie diese kleine Funktion verwenden:

def find_format_vars(string): 
    vars= {} 
    while True: 
     try: 
      string%vars 
      break 
     except KeyError as e: 
      vars[e.message]= '' 
    return vars.keys() 

>>> print find_format_vars("hello %(foo)s there %(bar)s") ['foo', 'bar']

3

Neuer Stil String forma Tting hat diese Fähigkeit.

from string import Formatter 

f = Formatter() 
x = "hello {foo}s there {bar}s" 
parsed = f.parse(x) 

Die Ergebnisse analysiert werden ein iterable von Tupeln mit diesem Format sein:
(literal_text, field_name, format_spec, Umwandlung)

So ist es einfach genug, um den field_name Abschnitt des Tupels zu ziehen:

field_names = [tup[1] for tup in parsed] 

Hier ist die Dokumentation, wenn Sie weitergehende Informationen wünschen https://docs.python.org/2/library/string.html#string.Formatter

Einzel Liste Verständnis Version:

[tup[1] for tup in "hello {foo}s there {bar}s"._formatter_parser()] 
+1

BTW in Python 2 ist so einfach wie: 'parsed = x._formatter_parse'. –

Verwandte Themen