8

我通常使用以下模式(如本问题所述):

a=1
s= "{a}".format(**locals())

我认为这是编写易于阅读的代码的好方法。

有时“链接”字符串格式很有用,以便“模块化”创建复杂字符串:

a="1"
b="2"
c="{a}+{b}".format(**locals())
d="{c} is a sum".format(**locals())
#d=="1+2 is a sum"

很快,代码就被X.format(**locals()). 为了解决这个问题,我尝试创建一个 lambda:

f= lambda x: x.format(**locals())
a="1"
b="2"
c= f("{a}+{b}")
d= f("{c} is a sum")

但这会引发 KeyError,因为locals()是 lambda 的本地变量。

我还尝试仅在最后一个字符串上应用格式:

a="1"
b="2"
c="{a}+{b}"
d="{c} is a sum".format(**locals())
#d=="{a}+{b} is a sum"

但这不起作用,因为 python 只格式化一次。现在,我可以编写一个重复格式化的函数,直到无事可做:

def my_format( string, vars ):
    f= string.format(**vars)
    return f if f==string else my_format(f, vars)

但我想知道:有没有更好的方法来做到这一点?

4

4 回答 4

4

f = lambda x, l=locals(): x.format(**l)似乎工作......

如果您想要一个更全面的版本(并且可能要慢很多):

fg = lambda x, l=locals(), g=globals(): x.format(**dict(g.items() + l.items()))

将在局部变量或全局变量中找到符号。

于 2013-10-23T18:55:30.977 回答
2

如果您只需要在函数范围内作为本地快捷方式执行此操作,则以下操作将起作用:

def formatter(fmt, loc=locals()):
    return fmt.format(**loc)

但是,这将绑定在locals()函数声明时返回的值,而不是执行,因此它不会随着值的变化而更新,也不会在从任何其他范围调用时有用。

如果你想访问调用方法的locals,你需要inspect调用堆栈(http://docs.python.org/2/library/inspect.html

import inspect

def formatter(fmt):
    parent = inspect.stack()[1][0] # 1 = the previous frame context
                                   # 0 = the frame object
    return fmt.format(**parent.f_locals)

请注意,这可能不适用于非 CPython 的 python 实现。

现在你可以这样做:

a = "1"
b = "2"
c = formatter("{a}+{b}")
d = formatter("{c} is a sum")
于 2013-10-23T20:56:55.657 回答
1

从 Python 3.6 开始, 的效果**locals()已经包含在string#format或者更确切地说是“格式化字符串文字”中。

另请参阅PEP 498Python 3.6 发行说明

于 2017-04-10T09:26:06.427 回答
0

它不是单行的,但它有效:

def fmt(s, l=locals()):
    while '{' in s:
        s = s.format(**l)
    return s

a="1"
b="2"
c="{a}+{b}"
d="{c} is a sum"

print fmt(d)  # 1+2 is a sum

这是一个单行(效率略低)的递归版本:

fmt = lambda s, l=locals(): fmt(s.format(**l), l=l) if '{' in s else s
于 2013-10-23T19:27:27.380 回答