【问题标题】:Change default float print format更改默认浮动打印格式
【发布时间】:2010-07-16 12:31:35
【问题描述】:

我有一些包含浮点数的列表和更复杂的结构。打印它们时,我看到带有很多十进制数字的浮点数,但是在打印时,我不需要所有的浮点数。 所以我想在打印浮点数时定义一个自定义格式(例如 2 位或 3 位小数)。

我需要使用浮点数而不是小数。另外,我不允许截断/舍入浮点数。

有没有办法改变默认行为?

【问题讨论】:

    标签: python python-3.x floating-point string-formatting


    【解决方案1】:

    您不能像 Ignacio 所说的那样对 C 类型进行monkeypatch。

    但是,如果您非常迫切地需要这样做并且您知道一些 C,您可以自己修改 Python 解释器源代码,然后将其重新编译为自定义解决方案。一旦我修改了列表的标准行为之一,它只是一个中度的痛苦。

    我建议您找到更好的解决方案,例如使用 "%0.2f" printf 表示法打印浮点数:

    for item in mylist:
        print '%0.2f' % item,
    

    print " ".join('%0.2f' % item for item in mylist)
    

    【讨论】:

    • 问题是我在列表中浮动,当我 print(list) 我无法控制它。 (这也适用于其他对象,顺便说一句)。修改源代码是可行的,因为我知道 C,但不完全是我的想法。谢谢。
    • @AkiRoss,如果您想要更多控制权,只需单独打印项目。
    • @Ignacio,如果我的对象使用 float.__str__ 或 float.__repr__ 来 str 或 repr 自己,我该怎么办?如果我嵌套了任意长度的列表怎么办?我认为修复这些是错误的。 Python提供了strrepr,我认为正确的方法是改变它们。我不知道它们对于 C 类型是固定的。
    • 另外,使用 Nick T 建议的自定义包装器,需要包装所有计算,我不能。
    • 如果 print 使用 str(obj) 将对象转换为字符串,我不能覆盖默认 str() 以返回自定义字符串,以防参数为浮点数并返回正常 str( ) 对于其余的?我正在阅读 PEP 3140
    【解决方案2】:
    >>> a = 0.1
    >>> a
    0.10000000000000001
    >>> print a
    0.1
    >>> print "%0.3f" % a
    0.100
    >>>
    

    Python docs 开始,repr(a) 将给出 17 位数字(在交互式提示符下只需键入 a 即可看到,但 str(a)(打印时自动执行)四舍五入为 12。

    编辑:最基本的黑客解决方案... 不过,您必须使用自己的课程,所以...是的。

    >>> class myfloat(float):
    ...     def __str__(self):
    ...             return "%0.3f" % self.real
    >>> b = myfloat(0.1)
    >>> print repr(b)
    0.10000000000000001
    >>> print b
    0.100
    >>>
    

    【讨论】:

      【解决方案3】:

      我今天遇到了这个问题,我想出了一个不同的解决方案。如果您担心打印时的外观,您可以将 stdout 文件对象替换为自定义对象,当调用 write() 时,该对象会搜索任何看起来像浮点数的内容,并将其替换为您自己的格式他们。

      class ProcessedFile(object):
      
          def __init__(self, parent, func):
              """Wraps 'parent', which should be a file-like object,
              so that calls to our write transforms the passed-in
              string with func, and then writes it with the parent."""
              self.parent = parent
              self.func = func
      
          def write(self, str):
              """Applies self.func to the passed in string and calls
              the parent to write the result."""
              return self.parent.write(self.func(str))
      
          def writelines(self, text):
              """Just calls the write() method multiple times."""
              for s in sequence_of_strings:
                  self.write(s)
      
          def __getattr__(self, key):
              """Default to the parent for any other methods."""
              return getattr(self.parent, key)
      
      if __name__ == "__main__":
          import re
          import sys
      
          #Define a function that recognises float-like strings, converts them
          #to floats, and then replaces them with 1.2e formatted strings.
          pattern = re.compile(r"\b\d+\.\d*\b")
          def reformat_float(input):
              return re.subn(pattern, lambda match: ("{:1.2e}".format(float(match.group()))), input)[0]
      
          #Use this function with the above class to transform sys.stdout.
          #You could write a context manager for this.
          sys.stdout = ProcessedFile(sys.stdout, reformat_float)
          print -1.23456
          # -1.23e+00
          print [1.23456] * 6
          # [1.23e+00, 1.23e+00, 1.23e+00, 1.23e+00, 1.23e+00, 1.23e+00]
          print "The speed of light is  299792458.0 m/s."
          # The speed of light is  3.00e+08 m/s.
          sys.stdout = sys.stdout.parent
          print "Back to our normal formatting: 1.23456"
          # Back to our normal formatting: 1.23456
      

      如果您只是将数字放入一个字符串中是不好的,但最终您可能希望将该字符串写入某个文件的某个地方,并且您可以使用上述对象包装该文件。显然有一点性能开销。

      公平警告:我尚未在 Python 3 中对此进行测试,我不知道它是否可行。

      【讨论】:

        【解决方案4】:

        不可以,因为这需要修改 float.__str__(),但您不能对 C 类型进行monkeypatch。改用字符串插值或格式化。

        【讨论】:

        • 其实需要修改float.__repr__str 仅使用 12 位有效数字。
        【解决方案5】:

        这并不能回答嵌套在其他结构中的浮点数更普遍的问题,但如果您只需要在列表甚至类似数组的嵌套列表中打印浮点数,请考虑使用numpy

        例如,

        import numpy as np
        np.set_printoptions(precision=3, suppress=False)
        list_ = [[1.5398, 2.456, 3.0], 
                 [-8.397, 2.69, -2.0]]
        print(np.array(list_))
        

        给予

        [[ 1.54   2.456  3.   ]
         [-8.397  2.69  -2.   ]]
        

        【讨论】:

          【解决方案6】:

          升级到 Python 3.1。它不会使用不必要的数字。

          Python 3.1.2 (r312:79147, Apr 15 2010, 15:35:48) 
          [GCC 4.4.3] on linux2
          Type "help", "copyright", "credits" or "license" for more information.
          >>> 0.1
          0.1
          

          【讨论】:

          • 已经在使用了。这不是重点,但感谢您的提示。
          【解决方案7】:

          如果你使用 C 语言,你可以使用#define"%*.*f" 这样做,例如

          printf("%*.*f",4,2,variable);
          

          【讨论】:

          • 他明确使用python标签,因此他没有使用C
          猜你喜欢
          • 2011-03-09
          • 1970-01-01
          • 2019-07-05
          • 1970-01-01
          • 2011-10-17
          • 2016-01-25
          • 2014-03-16
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多