【问题标题】:Using locals() and format() method for strings: are there any caveats?对字符串使用 locals() 和 format() 方法:有什么注意事项吗?
【发布时间】:2012-08-01 17:59:39
【问题描述】:

关于使用以下模式是否有任何缺点、注意事项或不良做法警告?

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)

【问题讨论】:

标签: python string-formatting local-variables locals


【解决方案1】:

现在有一种官方方法可以做到这一点,从 Python 3.6.0 开始:formatted string literals

它是这样工作的:

f'normal string text {local_variable_name}'

例如而不是这些:

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

这样做:

f"hello {name} you are {age} 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 完全符合您的需要。
    只是不要修改本地人的字典,我会说你有一个很好的解决方案。

    如果格式字符串是用户提供的,那么您很容易受到各种不良的注入攻击。

    【讨论】:

    • 不应该警告字符串永远不会用户提供吗?这可以打开对每个局部变量内容的访问。
    • 直拍@BobStein-VisiBone,我已经更新了答案。
    • 似乎使用 locals() 的性能开销非常小,而不仅仅是您需要的变量,因为您有一个额外的函数调用并且您正在构建一个更大的字典。不过,对于大多数应用程序来说,这可能可以忽略不计:我在快速测试用例中看到了大约 2% 的差异。
    • 可以说它是内部生成的,而不是用户提供的,这也适用于这里
    【解决方案3】:

    Pre Python 3.6 答案

    这已经很老了,但是如果您发现自己使用.format,我在传入**locals 时遇到的一个警告是,如果您没有在任何地方定义该变量,它将中断。在大多数现代 IDE 中,明确说明传入的变量将避免这种情况。

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

    【讨论】:

    • 使用这个:f"{foo} 和 {baz} 是结对编程" 你会得到一个 NameError。但在这种情况下,IDE 可以检测到它。应避免使用原始解决方案。只需在任何地方使用 f 字符串并强制使用 Python 3.6+ 此外,您将免费获得 asyncio 的语法。
    • @DeaD_EyE 我想我发现了一个 .format 仍然有用的情况:如果变量是在要格式化的字符串之后定义的。 s = """{foo} is not {bar}"""; foo = "A"; bar = "B"; f"{s}".format(**locals())
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-15
    • 1970-01-01
    • 2016-04-24
    • 2019-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多