2

カスタムクラスがあり、いくつかの人工演算子をオーバーロードしたいのですが、それぞれのコードを個別に書き出す必要がないようにする方法があるのではないかと思います。各演算子を1つずつ明示的にオーバーロードしない例を見つけることができませんでした。

class Foo(object):
    a=0 

    def __init__(self, a):
        self.a=a            

    def __add__(self, other):
        #common logic here
        return Foo(self.a+other.a)

    def __sub__(self, other):
        #common logic here  
        return Foo(self.a-other.a)

    def __mul__(self, other):
        #common logic here
        return Foo(self.a*other.a)

#etc...

ロジックはこれよりも少し複雑ですが、一般的なパターンは、各演算子のオーバーロードメソッドに、操作が許可されていることを確認するための同一のコードが含まれ、クラスメンバーを使用して操作を構築することです。冗長なコードを減らしたい。これは機能します:

class Foo(object):
    a=0 

    def __init__(self, a):
        self.a=a            

    def operate(self, other, operator):
        #common logic here
        a = constructOperation(self.a, other.a, operator)
        return Foo(a)

    def __add__(self, other):
        return self.operate(other, "+")

    def __sub__(self, other):       
        return self.operate(other, "-")     


def constructOperation(operand0, operand1, operator):
    if operator=="+": 
        return operand0 + operand1
    if operator=="-": 
        return operand0 - operand1

しかし、そのように手動で操作を構築するのはちょっとばかげているようです。このアプローチは理にかなっていますか、それともここでより良い方法がありますか?

4

4 に答える 4

6

リフレクションと高次関数を介して行うことができますが、これは継承ではうまくいかない場合があります。

import operator

def apply_a(func):
    def inner(self, other):
        return Foo(func(self.a, other.a))
    return inner

class Foo(object):
    def __init__(self, a=0):
        self.a = a

for name in ['__add__','__mul__','__sub__']:
    setattr(Foo, name, apply_a(getattr(operator, name)))
于 2013-03-04T07:26:03.293 に答える
5

operatorモジュールを使用するだけです:

import operator

class Foo(object):

    a=0 

    def __init__(self, a):
        self.a=a            

    def operate(self, other, op):
        #common logic here
        return Foo(op(self.a, other.a))

    def __add__(self, other):
        return self.operate(other, operator.add)

    def __sub__(self, other):       
        return self.operate(other, operator.sub)     
于 2013-03-04T07:28:29.447 に答える
1

すべての (または少なくともほとんどの) 演算子を定義しないようにする方法があるかどうかはわかりません。一つもないというのは理にかなっています。結局のところ、__sub__与えられた__add__(および__mul__) を定義する唯一の方法はありません。ただし、シンボリック演算子の代わりに callable を constructOperation() に渡すことで改善できます。

例えば

class Foo(object):
    a=0 

    def __init__(self, a):
        self.a=a            

    def operate(self, other, operator):
        #common logic here
        a = constructOperation(self.a, other.a, operator)
        return Foo(a)

    def __add__(self, other):
        return self.operate(other, sum)

    def __sub__(self, other):       
        return self.operate(other, lambda x, y: x - y)     


def constructOperation(operand0, operand1, operator):
    return operator(operand0, operand1)
于 2013-03-04T07:29:33.553 に答える
1

メソッドを定義する必要があります。これは、python が特別なメソッドを呼び出すときに特別なルックアップを行うためです。したがって、次のようになります。

import operator

class Foo(object):

    def __init__(self, a):
        self.a = a
    def __getattr__(self, attr):
        try:
            func = getattr(operator, attr)
            return lambda x: Foo(func(self.a, x.a))
        except AttributeError:
            raise AttributeError(attr)

動作しません:

>>> f = Foo(1)
>>> g = Foo(3)
>>> f * g     #no __mul__?
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for *: 'Foo' and 'Foo'
>>> getattr(f, '__mul__')
<function <lambda> at 0x2975140>
>>> f.__mul__(g)
<__main__.Foo object at 0x2922ed0>
>>> f.__mul__(g).a
3

あなたができる「最善」は、最も乾燥したアンチモンの溶液を使用することです.

于 2013-03-04T07:32:33.883 に答える