代码之家  ›  专栏  ›  技术社区  ›  Bananach

以旧代码计算的格式字符串执行计算

  •  2
  • Bananach  · 技术社区  · 7 年前

    我正在使用函数 foo (来自我无法修改的外部包)接受、填充和输出字符串。我想通过对该字符串中允许的间隙填充进行简单的算术来操纵输出。

    更明确地说:

    我现在打电话来 foo('Finished {n} out of {N}') 我得到,说, Finished 3 out of 5 jobs .

    我想去做 foo({N-n} left) 得到 2 jobs left

    目前这不起作用。我怀疑 简单的呼叫 format 在传递给它的字符串上 N-n 甚至不是有效的python变量名。

    问题:有没有办法欺骗 格式 做我想要的计算?丑陋的黑客是受欢迎的。

    编辑:这是针对python 3的 edit2:我没有访问变量的权限 N n . 它们是内部的

    edit3:假设可能和不可能的最小示例 实际上就是这样 .format 在传递给它的字符串上:

    import sys
    def foo(s):#This function cannot be changed
     N=5
     n=3
     sys.stderr.write(s.format(N=N,n=n))
    foo('Finished {n} out of {N}')
    foo('{N-n} left') # Error
    
    4 回复  |  直到 7 年前
        1
  •  1
  •   Nelewout    7 年前

    假设 foo 正如我们目前认为的那样,为什么不将python的 string 此特定案例的功能?

    class FooString(str):
    
        def format(self, **kwargs):
            if "n" not in kwargs or "N" not in kwargs:
                raise ValueError("Perhaps we're mistaken about foo?")
    
            return "Finished {n} out of {N}\n{left} left".format(
                left=kwargs["N"] - kwargs["n"], **kwargs)
    

    然后,打电话 foo(FooString()) 应产生所需的输出,

    >>>print(FooString().format(n=1, N=10))
    
    <<<Finished 1 out of 10
       9 left
    
        2
  •  3
  •   jpp    7 年前

    在python 3.6+中,可以使用格式化字符串文本( PEP 498 ,也称为F字符串。

    n = 3
    N = 5
    
    x = f'Finished {n} out of {N}'
    y = f'{N-n} jobs left'
    

    结果:

    print(x, y, sep='\n')
    
    Finished 3 out of 5
    2 jobs left
    

    如果您愿意的话,您可以将它包装在一个函数中。

        3
  •  2
  •   Jonathan    7 年前

    尝试:

    foo('{} left'.format(N-n))
    

    这应该能完成任务。这是一个非常简单的关于Python字符串格式化功能的例子。

    这里有一个建议的方法来做你想做的事情,基于你修改过的问题定义,但是它肯定是 非平凡的 . 它基于修改函数的python抽象语法树 foo .

    需要执行以下步骤:

    • 仅当您只有用于 功能。

      • 查找将生成python源代码的第三方解压程序
      • 为生成源代码 功能。
    • 用解析源代码 ast.parse()

    • 在函数中查找位置 N n 可靠可用。
    • 如果已经存在可以重写的print语句,请用代码替换它,否则将print语句插入树中。
    • 使用编译AST ast.compile() .
    • 使用结果函数对象代替原始函数。

    您将需要一个非常强大的用例来实现这一点,因为它将需要大量的学习和工作。没有实际 我能提供的功能很少。

        4
  •  0
  •   Bananach    7 年前

    我相信这可以通过调整python的属性查找来实现,正如 lazify 打包,然后在堆栈中搜索调用者的本地变量,但我放弃了这种方法,因为事情很快就会变得混乱。