在Python中子类化float以强制固定小数点打印精度
[Python 3.1]
我在跟进这个回答:
class prettyfloat(float):
def __repr__(self):
return "%0.2f" % self
我知道我需要注意我的浮点数(也就是把 3.0
替换成 prettyfloat(3.0)
等等),这没问题。
但是每当我进行计算时,prettyfloat
对象就会变成 float
。
有什么简单的方法可以解决这个问题吗?
编辑:
我需要保留两位小数;而且我希望在整个代码中都能这样,包括打印一个包含 float
值的字典。这让任何格式化函数都很难使用。
我不能使用 Decimal
的全局设置,因为我希望计算保持高精度(只是打印时保留两位小数)。
@Glenn Maynard:我同意我不应该重写 __repr__
;如果要重写的话,应该是 __str__
。不过这并不重要,因为有以下的原因。
@Glenn Maynard 和 @singularity:我不会去继承 float
,因为我同意这样最终看起来会很糟糕。
我决定不再尝试聪明的做法,而是在每次打印 float
的地方都调用一个函数。虽然我真的很遗憾不能在内置的 float
类中重写 __str__
。
谢谢大家!
3 个回答
使用 decimal
类型。这就是它的用途。
>>> import decimal
>>> decimal.getcontext().prec = 2
>>> one = decimal.Decimal("1.0")
>>> three = decimal.Decimal("3.0")
>>> one / three
Decimal('0.33')
...除非你真的想在代码中到处使用高精度的浮点数,但在打印的时候只显示到小数点后两位。那样的话,你就需要重新调整你的打印逻辑。
这是因为 prettyfloat (op) prettyfloat
不会返回一个 prettyfloat
类型的结果。
举个例子:
>>> prettyfloat(0.6)
0.60 # type prettyfloat
>>> prettyfloat(0.6) + prettyfloat(4.4)
5.0 # type float
如果你不想每次手动把操作结果转换成 prettyfloat
,而又想继续使用 prettyfloat
,那么可以重写所有的运算符。
这里以运算符 __add__
为例(虽然看起来不太好)。
class prettyfloat(float):
def __repr__(self):
return "%0.2f" % self
def __add__(self, other):
return prettyfloat(float(self) + other)
>>> prettyfloat(0.6) + prettyfloat(4.4)
5.00
这样做的话,我觉得你可能还得把 prettyfloat
的名字改成 uglyfloat
:) 希望这能帮到你。
我看了你提到的那个回答,觉得你可能搞混了数据和它的表现形式。
@Robert Rossney建议你可以通过创建一个float
的子类,这样你就可以用map()函数把一堆标准的、没有被修改过的floats
转换成prettyfloats
,这样做是为了显示效果:
# Perform all our computations using standard floats.
results = compute_huge_numbers(42)
# Switch to prettyfloats for printing.
print(map(prettyfloat, results))
换句话说,你不应该(也不需要)在代码的每个地方都用prettyfloat
来替代float
。
当然,从float
继承来解决这个问题有点过头了,因为这其实是一个表现形式的问题,而不是数据的问题。一个简单的函数就足够了:
def prettyfloat(number):
return "%0.2f" % number # Works the same.
现在,如果这根本不是关于表现形式的问题,而是你想在代码中实现固定小数点的计算,并且限制在两位小数,那就完全是另一回事了。