2012-08-01 11 views
35

Ci sono degli svantaggi, avvertimenti o avvisi di cattiva pratica sull'uso del seguente schema?Uso del metodo locals() e format() per le stringhe: ci sono dei caveat?

def buildString(user, name = 'john', age=22): 
    userId = user.getUserId() 
    return "Name: {name}, age: {age}, userid:{userId}".format(**locals()) 

ho avuto una generazione di codice di stringa molto ripetitivo a scrivere e fu tentato di utilizzare questo, ma qualcosa su come utilizzare locals() mi mette a disagio. C'è qualche pericolo di comportamento inaspettato in questo?

Edit: contesto

mi sono trovato costantemente scrivendo cose del genere:

"{name} {age} {userId} {etc}...".format(name=name, age=age, userId=userId, etc=etc) 
+1

Non vedo niente di terribilmente sbagliato ... – mgilson

+2

Bel trucco davvero! –

+2

Strettamente correlato a http://stackoverflow.com/q/1550479/125507 – endolith

risposta

8

Ora c'è un modo ufficiale per farlo a partire da Python 3.6.0: formatted string literals.

funziona così:

f'normal string text {local_variable_name}' 

Ad es invece di questi:

"hello %(name)s you are %(age)s years old" % locals() 
"hello {name}s you are {age}s years old".format(**locals()) 

solo fare questo:

f"hello {name}s you are {age}s years old" 

Ecco l'esempio ufficiale:

>>> name = "Fred" 
>>> f"He said his name is {name}." 
'He said his name is Fred.' 
>>> width = 10 
>>> precision = 4 
>>> value = decimal.Decimal("12.34567") 
>>> f"result: {value:{width}.{precision}}" # nested fields 
'result:  12.35' 

Riferimento:

26

Se la stringa di formato non è fornito dall'utente, questo uso è a posto.

format è preferibile all'uso del vecchio % per la sostituzione di stringhe.
locals è integrato in Python e il suo comportamento sarà affidabile.

Penso che locals faccia esattamente quello che ti serve.
Basta non modificare il dizionario dalla gente del posto e direi che hai una soluzione piuttosto buona.

Se la stringa di formato è fornita dall'utente, si è soggetti a attacchi di iniezione di tutti i tipi di cattiva qualità.

+3

Non dovrebbe esserci un avvertimento che la stringa non sia mai ** fornita dall'utente **? Questo potrebbe aprire l'accesso ai contenuti di ogni variabile locale. –

+0

Straight shooting @ BobStein-VisiBone, ho aggiornato la mia risposta. –

+0

Sembra che ci sia un overhead di prestazioni molto ridotto usando i locals() piuttosto che solo le variabili di cui hai bisogno, dal momento che hai una chiamata di funzione extra e stai costruendo un dizionario più grande. È probabilmente trascurabile per la maggior parte delle applicazioni: vedo differenze di circa il 2% in un caso di test rapido. – Widjet

0

Questo è molto vecchio, ma se vi trovate utilizzando l'.format un avvertimento che ho incontrato con il passaggio in **locals è che se non si dispone di tale variabile definita da nessuna parte, si romperà . Esplicitamente affermando quali variabili vengono passate eviterete ciò nella maggior parte dei moderni IDE.

foo = "bar" 
"{foo} and {baz} are pair programming".format(**locals) 
<exception occurs>