我有一些列表和包含浮点数的更复杂的结构。打印它们时,我看到带有很多十进制数字的浮点数,但是打印时,我不需要全部。 所以我想在打印浮点数时定义自定义格式(例如 2 或 3 位小数)。
我需要使用浮点数而不是十进制。另外,我不允许截断/舍入浮点数。
有办法改变默认行为吗?
你不被允许对 C 类型进行猴子补丁,就像 Ignacio 所说的那样。
但是,如果您迫于压力并且了解一些 C,您可以自己修改 Python 解释器源代码,然后将其重新编译为自定义解决方案。有一次我修改了列表的标准行为之一,这只是一种中等程度的痛苦。
我建议您找到更好的解决方案,例如仅使用
"%0.2f"
printf 表示法打印浮点数:
for item in mylist:
print '%0.2f' % item,
或
print " ".join('%0.2f' % item for item in mylist)
>>> a = 0.1
>>> a
0.10000000000000001
>>> print a
0.1
>>> print "%0.3f" % a
0.100
>>>
根据 Python 文档,
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
>>>
这并不能回答嵌套在其他结构中的浮点数的更普遍的问题,但如果您只需要在列表甚至类似数组的嵌套列表中打印浮点数,请考虑使用
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. ]]
不可以,因为这需要修改
float.__str__()
,但是不允许你对 C 类型进行猴子补丁。请改用字符串插值或格式化。
我今天遇到了这个问题,我想出了一个不同的解决方案。如果您担心打印时的样子,可以将 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 中测试过这个,我不知道它是否有效。
对于那些在 pandas 工作的人:
pd.options.display.float_format = "{:,.0f}".format
我知道这是一篇“旧”帖子,但是当我快速搜索网络以找到此解决方案时,我经常会得到旧的“解决方法”。如果我完全错过了一些东西,请提前道歉。
上面的代码将所有浮点数格式化为带有“千”分隔符的整数。其他小数位可以通过更改格式规范字符串来获得。
健康警告 - 这可能会使调试复杂化,因为所有输出(例如“打印”、“显示”和“描述”)也将输出适当舍入的数字。当某些浮点数实际上是不同的值时,它们会以不同的方式显示(即四舍五入),这可能会出现问题。
我刚刚整理了一种方法来实现这一点,至少对于 sympy 表达式,请参阅 this。 使用下面的两个函数,将每个
print(...
替换为 print_my(...
。
在我看来,与发布的大多数其他解决方案相比,这非常不做作,更易于使用且用途广泛。
我怀疑我的
round_expr
可以很容易地适应非sympy表达式,这是完整答案的缺失环节。
def round_expr(expr, num_digits):
"""Round all sp.Float numerical values in an expression to 3 decimal digits"""
return expr.xreplace({n.evalf() : n if isinstance(n, int) else sp.Float(n, num_digits) for n in expr.atoms(sp.Number)})
def print_my(*args, **kwargs):
end_my = kwargs['end'] if 'end' in kwargs else '\n'
sep_my = kwargs['sep'] if 'sep' in kwargs else ' '
for arg in args:
if (isinstance(arg, str)):
print(arg, end=sep_my)
elif (isinstance(arg, int)):
print(arg, **kwargs)
elif (isinstance(arg, float)):
print_my(sp.Float(arg), **kwargs)
elif (isinstance(arg, list)):
print('[', **kwargs)
for e in arg:
print_my(e, **kwargs)
if (not (e is arg[-1])):
print(', ', **kwargs)
print(']', **kwargs)
elif (isinstance(arg, dict)):
print('{', end='')
for k in arg.keys():
print_my(k, **kwargs)
print(': ', **kwargs)
print_my(arg[k], **kwargs)
print(', ', **kwargs)
print('}', **kwargs)
else:
# print(round_expr(arg, 3), end=sep_my)
print(round_expr(arg, 3), **kwargs)
print(end=end_my)
return
升级到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
如果你使用C语言,你可以使用
#define
或 "%*.*f"
来执行此操作,例如
printf("%*.*f",4,2,variable);