2014-12-31 7 views
9

Data una stringa di formattazione:Come posso ottenere l'elenco dei nomi utilizzati in una stringa di formattazione?

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

C'è un modo per ottenere i nomi delle variabili di formattazione? (Senza analizzarli direttamente io stesso).

L'utilizzo di un Regex non sarebbe stato troppo difficile, ma mi chiedevo se esistesse un modo più diretto per ottenerli.

+5

E '[molto facile] (https://docs.python.org/2/library/string.html#string.Formatter) se puoi passare alla nuova formattazione di stile. –

+0

non proprio un'opzione, sfortunatamente – qhfgva

risposta

7

Utilizzare una sottoclasse dict con metodo sovrascritto __missing__ e da lì si possono raccogliere tutte le variabili di formato mancanti:

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, questo è il metodo che ho deciso di usare. – qhfgva

3

I campi di formato sono significativi solo per l'operatore %, non per la stringa stessa. Quindi, non esiste un attributo come str.__format_fields__ a cui è possibile accedere per ottenere i nomi dei campi.

Direi che l'utilizzo di Regex è in realtà l'approccio corretto in questo caso. Si può facilmente utilizzare re.findall per estrarre i nomi:

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

seguito è una spiegazione del modello:

(?<!%)    # 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

Cercherò anche uno dei caratteri di formattazione validi dopo la parentesi di chiusura; '[diouxXeEfFgGcrs]' dovrebbe fare. –

+0

Lì, penso di aver appianato tutti i nodi. :) – iCodez

+0

Che dire di '" ciao %%% (foo) "'? – Kobi

5

Se non si desidera analizzare la stringa, è possibile utilizzare questa funzione poco:

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

Nuova stringa stile forma tting ha questa capacità.

from string import Formatter 

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

I risultati analizzati saranno un iterabile di tuple con questo formato:
(literal_text, field_name, format_spec, conversione)

Quindi è abbastanza semplice per tirare fuori la sezione nome_campo della tupla:

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

Ecco la documentazione, se volete maggiori informazioni approfondite https://docs.python.org/2/library/string.html#string.Formatter

singola versione lista-di comprensione:

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

BTW in Python 2 è semplice come: 'parsed = x._formatter_parse'. –

Problemi correlati