为啥不能为非浮点数定义“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])) 正确产生5round(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”?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 std::abs() 不能与浮点数一起使用

为啥 math.inf 是浮点数,为啥我不能将其转换为整数?

OpenGL:为啥我不能将单个浮点数从顶点着色器传递到片段着色器?

为啥 SQL 浮点数与 C# 浮点数不同

php浮点数

为啥 % 运算符不能用于 C/C++ 中的浮点数但可以用于 Java 和 C#? [复制]