Pequena dica de Python: string formatting com locals()

Há muitas situações em que uma função faz cálculos e operações para obter valores e, ao final, deve montar uma string com esses valores. Nesta situação, muita gente monta um dicionário com os valores e usa string formatting para gerar a string a ser retornada. Por exemplo:

# -*- encoding: utf-8 -*-
import string,random

template='''Sugestões para %(nome)s:
 - login: %(login)s
 - email: %(email)s
 - site: www.%(domain)s.com
 - senha: %(passwd)s
'''

def sugere_logins(nome):
    login=nome.split(' ')[0].lower()
    domain=nome.split(' ')[-1].lower()
    email=login+'@'+domain+'.com'
    chars=string.letters+string.digits
    passwd=''.join(random.sample(chars,10))
    dados={'login':login,
           'email':email,
           'nome':nome,
           'domain':domain,
           'passwd':passwd}
    print template % dados

Você pode substituir todo o trecho em que monta o dicionário, usando o resultado da função locals(). A função locals() retorna um dicionário com todas as variáveis locais. No exemplo acima, isso ficaria assim:

# -*- encoding: utf-8 -*-
import string,random

template='''Sugestões para %(nome)s:
 - login: %(login)s
 - email: %(email)s
 - site: www.%(domain)s.com
 - senha: %(passwd)s
'''

def sugere_logins(nome):
    login=nome.split(' ')[0].lower()
    domain=nome.split(' ')[-1].lower()
    email=login+'@'+domain+'.com'
    chars=string.letters+string.digits
    passwd=''.join(random.sample(chars,10))
    print template % locals()

Uso muito esse truque ao trabalhar com web2py, fazendo com que os controllers, ao invés de retornar um dicionário montado por mim, retornem locals().

3 comments on “Pequena dica de Python: string formatting com locals()

  1.  No meu comentário anterior, a atribuição ao meu_locals não precisa. Eu estava com outro código em mente antes, e acabei esquecendo o gaiato ali. #fail rsrsrs

  2. Formatar strings com locals() (ou qualquer outro dicionário com muitas chaves) é bem útil e economiza código. 😉

    Eu só não recomendaria a parte do return locals() p/ um template se a função usar muitas variáveis. Isso só é bom na hora de escrever o código. Depois, quem vai dar manutenção sofre pra descobrir se determinada variável é usada no template. Principalmente se houver inclusão de outro template, por exemplo.

    Para economizar código, a partir do Python 2.7, é possível usar dict_comprehension para deixar o antigo return locals() mais explícito, assim:
    >>> meu_locals = locals()
    >>> return {key: meu_locals.get(key) for key in ‘campo1 campo2 campo3’.split()}

    Antes da v2.7 também era possível retornando tuplas e criando o dicionário com dict(), assim:
    >>> return dict([(key, meu_locals.get(key)) for key in ‘campo1 campo2 campo3’.split()])

    Mas, claro, se sua função usar poucas variáveis, até que o return locals() ajuda, né? 😉

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *