【问题标题】:sprintf like functionality in PythonPython中的类似sprintf的功能
【发布时间】:2011-07-15 15:54:56
【问题描述】:

我想创建一个字符串缓冲区来进行大量处理、格式化,最后使用 Python 中的 C 风格 sprintf 功能将缓冲区写入文本文件。由于条件语句,我不能直接将它们写入文件。

例如伪代码:

sprintf(buf,"A = %d\n , B= %s\n",A,B)
/* some processing */
sprint(buf,"C=%d\n",c)
....
...
fprintf(file,buf)

所以在输出文件中我们有这种o/p:

A= foo B= bar
C= ded
etc...

编辑,澄清我的问题:
buf 是一个大缓冲区,包含所有这些使用 sprintf 格式化的字符串。 按照您的示例,buf 将仅包含当前值,而不包含旧值。 例如,首先在buf 中我写了A= something ,B= something,后来C= something 被附加在同一个buf 中,但在你的Python 答案中buf 只包含最后一个值,这不是我想要的-我希望buf 有我从一开始就做的所有printfs,比如C

【问题讨论】:

  • 这不是 sprintf() 在 C 中的工作方式。(它将内容写入 buf 的开头,而不是结尾。)使用字符串数组可能效果最好,然后在写入文件之前将它们连接在一起。
  • @dividebyzero 这在 Python 中是不是很简单,因为它是一种通用编程语言?例如,请参阅Michael J. Barber's solution(在您发表评论后发布)。 def sprintf(buf, fmt, *args): ...
  • @jdk1.0 我不知道我的意思,我是一个年轻而天真的 Python 程序员......这个问题实际上很奇怪,因为这个缓冲区重用并不是那么简单,你需要用每个 sprintf 调用的输出增加一个指针,如果你在做 Python,这种事情不是你应该担心的。无论如何,我很高兴我转向了 Scala,现在转向了 Julia!

标签: python string


【解决方案1】:

我知道这是一个旧线程 - 但有一个新的字符串插值“样式” - f'' 字符串格式化构造。

a = 5
b = "hello"
buf = f"A = {a:d}\n , B = {b}\n" 

PEP-498 中指定了F-String(被称为)。

在学习 F-String 之前,我会像这样调用格式:

a = 5
b = "hello"
buf = "A = {a:d}\n , B = {b}\n".format( **{ **globals() , **locals() } ) 

根据 PEP-498 文档,F-String 在 Python 3.6 或更高版本中可用。

【讨论】:

    【解决方案2】:

    使用 formatting operator % : buf = "A = %d\n , B= %s\n" % (a, b) 打印 >>f, buf

    【讨论】:

      【解决方案3】:

      类似...

      greetings = 'Hello {name}'.format(name = 'John')
      
      Hello John
      

      【讨论】:

      • 这也将 %s 打印到屏幕上,这是意料之外的;但我喜欢我可以用逗号添加多个变量。
      【解决方案4】:

      两种方法是写入字符串缓冲区或将行写入列表并稍后加入。我认为StringIO 方法更符合 Python 风格,但在 Python 2.6 之前不起作用。

      from io import StringIO
      
      with StringIO() as s:
         print("Hello", file=s)
         print("Goodbye", file=s)
         # And later...
         with open('myfile', 'w') as f:
             f.write(s.getvalue())
      

      您也可以在没有ContextMananger (s = StringIO()) 的情况下使用它们。目前,我正在使用带有print 函数的上下文管理器类。该片段可能有助于插入调试或奇数分页要求:

      class Report:
          ... usual init/enter/exit
          def print(self, *args, **kwargs):
              with StringIO() as s:
                  print(*args, **kwargs, file=s)
                  out = s.getvalue()
              ... stuff with out
      
      with Report() as r:
         r.print(f"This is {datetime.date.today()}!", 'Yikes!', end=':')
      

      【讨论】:

        【解决方案5】:

        如果你想要类似 python3 的 print 函数,但需要一个字符串:

        def sprint(*args, **kwargs):
            sio = io.StringIO()
            print(*args, **kwargs, file=sio)
            return sio.getvalue()
        
        >>> x = sprint('abc', 10, ['one', 'two'], {'a': 1, 'b': 2}, {1, 2, 3})
        >>> x
        "abc 10 ['one', 'two'] {'a': 1, 'b': 2} {1, 2, 3}\n"
        

        或者在末尾没有'\n'

        def sprint(*args, end='', **kwargs):
            sio = io.StringIO()
            print(*args, **kwargs, end=end, file=sio)
            return sio.getvalue()
        
        >>> x = sprint('abc', 10, ['one', 'two'], {'a': 1, 'b': 2}, {1, 2, 3})
        >>> x
        "abc 10 ['one', 'two'] {'a': 1, 'b': 2} {1, 2, 3}"
        

        【讨论】:

        • 不知道为什么其他所有答案都在回避实际问题。谢谢你。
        【解决方案6】:

        我不完全确定我理解您的目标,但您可以使用 StringIO 实例作为缓冲区:

        >>> import StringIO 
        >>> buf = StringIO.StringIO()
        >>> buf.write("A = %d, B = %s\n" % (3, "bar"))
        >>> buf.write("C=%d\n" % 5)
        >>> print(buf.getvalue())
        A = 3, B = bar
        C=5
        

        sprintf 不同,您只需将字符串传递给buf.write,使用% 运算符或字符串的format 方法对其进行格式化。

        您当然可以定义一个函数来获取您希望的sprintf 接口:

        def sprintf(buf, fmt, *args):
            buf.write(fmt % args)
        

        会这样使用:

        >>> buf = StringIO.StringIO()
        >>> sprintf(buf, "A = %d, B = %s\n", 3, "foo")
        >>> sprintf(buf, "C = %d\n", 5)
        >>> print(buf.getvalue())
        A = 3, B = foo
        C = 5
        

        【讨论】:

        • +1 向我展示了如何将 *args 与字符串格式化运算符 (%) 一起使用。
        • 对于 Python3 使用 io.StringIO() 代替
        【解决方案7】:

        要插入一个很长的字符串,最好为不同的参数使用名称,而不是希望它们位于正确的位置。这也使得替换多次重复变得更容易。

        >>> 'Coordinates: {latitude}, {longitude}'.format(latitude='37.24N', longitude='-115.81W')
        'Coordinates: 37.24N, -115.81W'
        

        取自Format examples,其中还显示了所有其他与Format 相关的答案。

        【讨论】:

          【解决方案8】:

          Python 对此有一个 % 运算符。

          >>> a = 5
          >>> b = "hello"
          >>> buf = "A = %d\n , B = %s\n" % (a, b)
          >>> print buf
          A = 5
           , B = hello
          
          >>> c = 10
          >>> buf = "C = %d\n" % c
          >>> print buf
          C = 10
          

          查看此reference 了解所有支持的格式说明符。

          你也可以使用format:

          >>> print "This is the {}th tome of {}".format(5, "knowledge")
          This is the 5th tome of knowledge
          

          【讨论】:

            【解决方案9】:

            这可能是从 C 代码到 Python 代码的最接近的翻译。

            A = 1
            B = "hello"
            buf = "A = %d\n , B= %s\n" % (A, B)
            
            c = 2
            buf += "C=%d\n" % c
            
            f = open('output.txt', 'w')
            print >> f, c
            f.close()
            

            Python 中的 % 运算符与 C 中的 sprintf 几乎完全相同。您也可以直接将字符串打印到文件中。如果涉及大量此类字符串格式的 stringlet,则使用StringIO 对象来加快处理时间可能是明智之举。

            所以不要做+=,而是这样做:

            import cStringIO
            buf = cStringIO.StringIO()
            
            ...
            
            print >> buf, "A = %d\n , B= %s\n" % (A, B)
            
            ...
            
            print >> buf, "C=%d\n" % c
            
            ...
            
            print >> f, buf.getvalue()
            

            【讨论】:

              【解决方案10】:

              如果我正确理解您的问题,format()its mini-language 就是您要查找的内容。

              python 2.7 及更高版本的愚蠢示例:

              >>> print "{} ...\r\n {}!".format("Hello", "world")
              Hello ...
               world!
              

              对于较早的 python 版本:(使用 2.6.2 测试)

              >>> print "{0} ...\r\n {1}!".format("Hello", "world")
              Hello ...
               world!
              

              【讨论】:

              • 您可能应该注意到,该版本仅适用于 Python 3。例如,在 Python 2.6 中,您需要这样做:"{0} ...\r\n {1}!".format("Hello", "world")
              • 编辑我的答案以包含它;不要说它也适用于python 2.7!
              【解决方案11】:

              您可以使用字符串格式:

              >>> a=42
              >>> b="bar"
              >>> "The number is %d and the word is %s" % (a,b)
              'The number is 42 and the word is bar'
              

              但这在 Python 3 中被删除了,你应该使用“str.format()”:

              >>> a=42
              >>> b="bar"
              >>> "The number is {0} and the word is {1}".format(a,b)
              'The number is 42 and the word is bar'
              

              【讨论】:

              • 错了,它在 Python 3 中没有被删除。Python 3.0 说它会在 3.1 中被弃用,但我相信这从未发生过。使用format() 可能更可取,但% 格式仍然存在。 (请参阅mail.python.org/pipermail/python-dev/2009-September/092399.html 了解它未被弃用的一些原因)
              • @Duncan;谢谢,我不知道。我在某个地方读到它已弃用,再也没有尝试过:)。
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2017-05-21
              • 2020-09-23
              • 2017-05-06
              • 2022-01-23
              相关资源
              最近更新 更多