Использование методов locals() и format() для строк: существуют ли какие-либо оговорки?

Существуют ли какие-либо недостатки, оговорки или предупреждения о плохой практике об использовании следующего шаблона?

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

У меня был очень повторяющийся код генерации строки для записи, и у меня возникло соблазн использовать это, но что-то об использовании locals() делает меня неудобным. Есть ли в этом опасность неожиданного поведения?

Изменить: контекст

Я обнаружил, что постоянно пишу такие вещи, как:

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

Ответ 1

Теперь есть официальный способ сделать это, начиная с Python 3.6.0: форматированные строковые литералы.

Это работает так:

f'normal string text {local_variable_name}'

Э.Г. вместо них:

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

просто сделай это:

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

Вот официальный пример:

>>> 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'

Ссылка:

Ответ 2

Если строка формата не предоставляется пользователем, это использование в порядке.

format предпочтительнее использования старой % для замены строки.
locals встроен в Python, и его поведение будет надежным.

Я думаю, что locals делает именно то, что вам нужно.
Просто не изменяйте словарь от локальных жителей, и я бы сказал, что у вас довольно хорошее решение.

Если строка формата предоставлена ​​пользователем, вы подвержены атакам при инъекциях всякого рода неприятностей.

Ответ 4

Ответ до Python 3.6

Это очень старо, но если вы обнаружите, что используете .format, то единственное предостережение, с которым я столкнулся при передаче в **locals, заключается в том, что если вы не определили эту переменную где-либо, она сломается. Явное указание передаваемых переменных позволит избежать этого в большинстве современных IDE.

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