为啥不能为非浮点数定义“round”?
Posted
技术标签:
【中文标题】为啥不能为非浮点数定义“round”?【英文标题】:Why can't `round` be defined for non-floats?为什么不能为非浮点数定义“round”? 【发布时间】:2013-04-10 03:01:46 【问题描述】:给定一个简单的类
class Vector(object):
def __init__(self, value):
self.value = value
def __abs__(self):
return math.sqrt(sum([x**2 for x in self.value]))
def __round__(self, *n):
return [round(x,*n) for x in self.value]
为什么abs(Vector([-3,4]))
正确产生5
而round(Vector([-3.1,4]))
抱怨TypeError: a float is required
而不是所需的[-3,4]
,如何解决这个问题?
我知道round
通常应该返回一个浮点数,但是对于本例中的向量,可能的含义可能没有歧义,那么为什么不能简单地覆盖它呢?我真的必须继承numbers.Real
,还是定义Vector(...).round(n)
?
【问题讨论】:
【参考方案1】:__round__
特殊方法仅在 Python 3 中引入。Python 2 中不支持该特殊方法。
您必须使用专用方法而不是函数:
class Vector(object):
def __init__(self, value):
self.value = value
def round(self, n):
return [round(x, n) for x in self.value]
或者您必须提供自己的 round()
函数:
import __builtin__
def round(number, digits=0):
try:
return number.__round__(digits)
except AttributeError:
return __builtin__.round(number, digits)
您甚至可以将其修补到 __builtins__
命名空间中:
import __builtin__
_bltin_round = __builtin__.round
def round(number, digits=0):
try:
hook = number.__round__
except AttributeError:
return _bltin_round(number, digits)
else:
# Call hook outside the exception handler so an AttributeError
# thrown by its implementation is not masked
return hook(digits)
__builtin__.round = round
【讨论】:
我明白了,在这种情况下,我也应该标记问题python-2.7...这同样适用于math.floor
等人吗?没有from __future__ import
来解决这个问题吗?
不,很遗憾,没有from __future__
开关可以启用该行为。
无赖 :-( 那是一个非常有说服力的论点,让我切换到 Python 3...
@TobiasKienzler 或者,您可以只修补 round
函数(即使这是不好的风格)
@TobiasKienzler:完全正确;并且__builtins__
(带有s
)在任何地方都是一个字典,除了在主脚本(__name__ == '__main__'
)中它是一个模块对象。使用__builtin__
可以让你更轻松不必记住处理任何一种情况。以上是关于为啥不能为非浮点数定义“round”?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 math.inf 是浮点数,为啥我不能将其转换为整数?