在字符串格式化中捕获 **vars() 模式
我经常使用以下这种方式来格式化字符串。
a = 3
b = 'foo'
c = dict(mykey='myval')
#prints a is 3, b is foo, mykey is myval
print('a is {a}, b is {b}, mykey is {c[mykey]}'.format(**vars()))
也就是说,我常常需要打印的值都在本地命名空间里,可以通过调用 vars() 来获取。不过,当我回头看我的代码时,发现一直重复使用 .format(**vars())
这种写法,感觉有点不太符合 Python 的风格。
我想创建一个函数,能够捕捉到这种写法。它的样子大概是这样的。
# doesn't work
def lfmt(s):
"""
lfmt (local format) will format the string using variables
in the caller's local namespace.
"""
return s.format(**vars())
但是,当我进入 lfmt
命名空间时,vars() 就不再适用了。
我该如何编写 lfmt 函数,让它在调用者的命名空间中执行 vars(),这样下面的代码就能像上面的例子一样工作呢?
print(lfmt('a is {a}, b is {b}, mykey is {c[mykey]}'))
5 个回答
0
给你看看:
import sys
def lfmt(s):
"""
lfmt (local format) will format the string using variables
in the caller's local namespace.
"""
if hasattr(sys, "tracebacklimit") and sys.tracebacklimit == 0:
raise Exception, "failfailfail"
try:
raise ZeroDivisionError
except ZeroDivisionError:
f = sys.exc_info()[2].tb_frame.f_back
return s.format(**f.f_locals)
a = 5
somestring = "text"
print lfmt("{a} {somestring}")
它能用并不代表你就应该用。这种情况在开发者中被称为“重大黑客行为”,通常会附带一个评论“XXX 修复我 XXX”。
1
你需要查看调用框架中的变量。
这将帮助你入门:
import inspect
import pprint
def lfmt(s):
for frame in inspect.getouterframes(inspect.currentframe()):
f = frame[0]
print pprint.pformat(f.f_locals)
return '???'
if __name__ == '__main__':
a = 10
b = 20
c = 30
lfmt('test')
2
编辑: 为了让 lfmt
在不同的命名空间中调用时正常工作,你需要使用 inspect
模块。需要注意的是,正如文档所警告的,inspect
模块可能不适合用于生产环境,因为它可能在所有的 Python 实现中都无法正常工作。
import inspect
def lfmt(s):
caller = inspect.currentframe().f_back
return s.format(**caller.f_locals)
a = 3
b = 'foo'
c = dict(mykey='myval')
print(lfmt('a is {a}, b is {b}, mykey is {c[mykey]}'))
# a is 3, b is foo, mykey is myval