我有一个不带参数的函数并返回一个字符串,我想用字符串格式调用它。这就是,这就是我尝试使用format
:
def cabbages():
return 'hello'
In [2]: '{cabbages} world'.format(**locals())
Out[2]: '<function cabbages at 0x101f75578> world'
In [3]: '{cabbages()} world'.format(**locals())
KeyError: 'cabbages()'
所以这两者都不是我想要的,即cabbages()
的价值。
PEP 3101描述了string.Formatter
可被覆盖的某种方式,但似乎没有提供很多示例。如何对字符串Formatter
类进行子类化/自定义来执行此操作?
我考虑的一个hacky事件是覆盖__getattr__
的{{1}}方法,我真的不希望被“视为病态”(或,至少,* * * pathological)。
答案 0 :(得分:2)
我想我在你的答案中看到的主要缺点是,它还没有处理原始的复合字段名称语法,例如0.name
用于'getattr'/'dot'操作员访问,0[name]
用于在PEP 3101中指定的'getitem'检索。
这是一个适用于Python 2.7和3.3的版本。一个主要的实现差异是它覆盖get_value()
方法而不是get_field()
。
虽然它在如何检测get_value()
方法中的调用方面有些苛刻,但我认为它不会被视为病态。 ; - )
from __future__ import print_function
from string import Formatter
class CallFormatter(Formatter):
try: # deal with Py 2 & 3 difference
NUMERICS = (int, long)
except NameError:
NUMERICS = int
def get_value(self, key, args, kwargs):
if key.endswith('()'): # call?
return kwargs[key[:-2]]()
elif isinstance(key, self.NUMERICS):
return args[key]
else:
return kwargs[key]
if __name__ == '__main__':
fmt = CallFormatter()
def cabbages():
return 'hello'
d = dict(name='Fred')
class Thing(object):
def __init__(self, value):
self.attr = value
th = Thing(42)
print('d[name]:{d[name]}, th.attr:{th.attr}, '
'cabbages:{cabbages}'.format(**locals()))
print(fmt.format('d[name]:{d[name]}, th.attr:{th.attr}, '
'cabbages:{cabbages}, cabbages():{cabbages()}',
**locals()))
输出:
d[name]:Fred, th.attr:42, cabbages:<function cabbages at 0x00BB05F0>
d[name]:Fred, th.attr:42, cabbages:<function cabbages at 0x00BB05F0>,
cabbages():hello
答案 1 :(得分:1)
您可以按如下方式覆盖Formatter
from string import Formatter
class CallFormatter(Formatter):
def get_field(self, field_name, *args, **kwargs):
obj, used_key = Formatter.get_field(self, field_name, *args, **kwargs)
return obj(), used_key # obj is the function
fmt = CallFormatter()
In [11]: fmt.format('{cabbages} world', **locals())
Out[11]: 'hello world'
方法:
{{1}}
做这样的事情带有健康警告,所以我认为值得完全粘贴get_field
的安全注意事项部分(强调添加):
历史上,字符串格式化是的常见来源 基于Web的应用程序中的安全漏洞,尤其是在 字符串格式化系统允许任意表达式 嵌入格式字符串。
使用字符串格式化的最佳方式 创建潜在的安全漏洞是从不使用格式字符串 来自不受信任的来源。
除此之外,下一个最好的方法是确保字符串 格式化没有副作用。因为开放性 Python,无法保证任何非平凡的 操作有这个属性。 PEP的作用是限制 格式字符串中的表达式类型与可见的格式 副作用既罕见又强烈劝阻 Python开发人员的文化。例如,属性访问 是允许的,因为写入会被认为是病态的 仅仅访问属性的代码具有可见的一面 效果(代码是否具有不可见副作用 - 如此 为更快的查找创建缓存条目 - 无关紧要。)