概要
我非常喜欢f-strings。它们是一种非常棒的语法。
有段时间以来,我一直有一个小型库的想法,如下所述,用于进一步利用它们。这里有一个快速的示例来说明我想让它做什么:
>>> import simpleformatter as sf
>>> def format_camel_case(string):
... """camel cases a sentence"""
... return ''.join(s.capitalize() for s in string.split())
...
>>> @sf.formattable(camcase=format_camel_case)
... class MyStr(str): ...
...
>>> f'{MyStr("lime cordial delicious"):camcase}'
'LimeCordialDelicious'
为了简化API,扩展内置类实例的用途,找到一种方法来连接内置Python格式化机制将非常有用。这将允许自定义内置格式规范:
>>> f'{"lime cordial delicious":camcase}'
'LimeCordialDelicious'
换句话说,我想覆盖内置的
format
函数(该函数被f-string语法使用)--或者,扩展现有标准库类的内置__format__
方法--以便我可以编写像这样的代码:for x, y, z in complicated_generator:
eat_string(f"x: {x:custom_spec1}, y: {x:custom_spec2}, z: {x:custom_spec3}")
我通过创建具有自己的__format__
方法的子类来完成了这一点,但当然这对于内置类不起作用。
使用string.Formatter
API,我可以接近实现它:
my_formatter=MyFormatter() # custom string.Formatter instance
format_str = "x: {x:custom_spec1}, y: {x:custom_spec2}, z: {x:custom_spec3}"
for x, y, z in complicated_generator:
eat_string(my_formatter.format(format_str, **locals()))
我认为这有点笨重,与f-string api相比肯定不易读。
另一件事是可以覆盖builtins.format
:
>>> import builtins
>>> builtins.format = lambda *args, **kwargs: 'womp womp'
>>> format(1,"foo")
'womp womp'
但是这对f-strings无效:
>>> f"{1:foo}"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: Invalid format specifier
细节
目前 我的API 大致如下(有些地方做了简化):
import simpleformatter as sf
@sf.formatter("this_specification")
def this_formatting_function(some_obj):
return "this formatted someobj!"
@sf.formatter("that_specification")
def that_formatting_function(some_obj):
return "that formatted someobj!"
@sf.formattable
class SomeClass: ...
之后您可以像这样编写代码:
some_obj = SomeClass()
f"{some_obj:this_specification}"
f"{some_obj:that_specification}"
我希望API更像下面这样:
@sf.formatter("this_specification")
def this_formatting_function(some_obj):
return "this formatted someobj!"
@sf.formatter("that_specification")
def that_formatting_function(some_obj):
return "that formatted someobj!"
class SomeClass: ... # no class decorator needed
...并允许在内置类上使用自定义格式规范:
x=1 # built-in type instance
f"{x:this_specification}"
f"{x:that_specification}"
但是,为了做到这些事情,我们必须深入挖掘内置的format()
函数。那么我该如何接入这个美妙的f-string功能呢?
* 注意:我可能永远不会真正实现这个库!但是我认为这是一个很棒的想法,欢迎任何想要偷走它的人 :)。
f"{spec(x)}"
吗? - Davis Herringf("{x:spec}")
,可以使用string.Formatter
以及inspect.currentframe().f_back
.f_locals
和.f_globals
(参见 https://docs.python.org/3/library/inspect.html 和 https://dev59.com/HGw15IYBdhLWcg3wbbNx)?您还可以使用运算符,例如@
来改进语法 (f@"{x:spec}"
)。 - Solomon Uckof@
的想法相当有创意!缺点是:没有前导的 f,IDE 将不知道字符串包含表达式。但这几乎不会成为阻碍。 - Rickv_eval(f'<v lang code>{x!v}<more v code>')
的东西就太好了,其中x
是Python变量,它被插入到v-lang代码中,即通过转换它并提供某些v理解的参考。 - Will Da Silva