5
class Number(object):
    def __init__(self):
        super(Number, self).__init__()
        self.data = 10

    def __getattr__(self, name):
        def _missing(*args, **kwargs):
            method = getattr(self.data, name)
            return method(args[0])

        return _missing

a = Number()
b = Number()

print a.__add__(10)   # this is ok!
print a + 10          # TypeError: "unsupported operand type(s) for +: 'Number' and 'int'"
print a + b           # TypeError: "unsupported operand type(s) for +: 'Number' and 'Number'"

質問: "a.__add__(10)" と "a + 10" の違いは何ですか? 演算子 "+" をフックするにはどうすればよいですか?

4

2 に答える 2

5

Python は、 の__add__ために「存在する」だけのメソッドではなく、実際のメソッドのみを使用し__getattr__ます。

追加する__add__ = (10).__add__とうまくいきます。

したがって、プロキシ メソッドを追加する必要があります。

def __add__(self, *args): return self.data.__add__(*args)
def __sub__(self, *args): return self.data.__sub__(*args)
# ...
于 2012-07-24T10:56:15.530 に答える
1

これを試すことができますが、美しくありません:

import numbers

def redirect(name):
    def redirected(self, *args):
        assert len(args) <= 1
        if len(args) == 1 and isinstance(args[0], Number):
            return getattr(self._data, name)(args[0]._data)
        else:
            return getattr(self._data, name)(*args)
    return redirected

names = set(['__gt__', '__ge__'])
names.update(numbers.Real.__abstractmethods__)
methods = dict((name, redirect(name)) for name in names)
methods.update(
    {'__init__': lambda self, data: setattr(self, '_data', float(data))})
Number = type("Number", (), methods)

次のように使用できます。

>>> a = Number(5)
>>> b = Number(7)
>>> a + 10
15.0
>>> a + b
12.0
>>> a > b
False
>>> a == Number(5.0)
True

算術演算子から返される型は isfloatであり、notであることに注意してくださいNumber(これは、期待したものである場合とそうでない場合があります)。

整数が必要な場合は、float()呼び出しを削除して に変更numbers.Realできnumbers.Integralます。ただし、算術演算子は float 値で機能しなくなることに注意してください。

于 2015-05-17T15:52:40.960 に答える