【问题标题】: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)

【问题讨论】:

    标签: python class python-2.7 rounding


    【解决方案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__可以让你更轻松不必记住处理任何一种情况。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-03
    • 1970-01-01
    • 1970-01-01
    • 2019-12-30
    • 2010-09-12
    • 1970-01-01
    • 2012-03-17
    相关资源
    最近更新 更多