代码之家  ›  专栏  ›  技术社区  ›  Rick SilentGhost

钩住内置的python f-string格式机制

  •  2
  • Rick SilentGhost  · 技术社区  · 5 年前

    我真的很喜欢 f-strings

    我写了一个小的库-如下所述-供我自己进一步利用它们(和 put it out there for use by others ,以防对他们有帮助;编辑:我真的还没有完成这个库,所以不要太兴奋)。举一个简单的例子说明它做了什么/将要做什么:

    >>> 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}")
    

    我通过创建子类来实现这一点

    我可以用 string.Formatter 应用程序编程接口:

    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()))
    

    另一件可以做的事是压倒一切 builtins.format

    >>> import builtins
    >>> builtins.format = lambda *args, **kwargs: 'womp womp'
    >>> format(1,"foo")
    'womp womp'
    

    …但这不适用于f字符串:

    >>> f"{1:foo}"
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: Invalid format specifier
    

    目前 my 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弦呢?

    0 回复  |  直到 4 年前