为什么不能`round`被非花车定义?(Why can't `round` be defin

2019-08-31 09:10发布

给定一个简单的类象

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)呢?

Answer 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


文章来源: Why can't `round` be defined for non-floats?