5

>>演算子をオーバーロードする必要があるPythonプログラムを書いています。私が直面している問題は、この演算子が正しく結合する必要があるということです。だから私が次のことをすると

A >> B >> C >> D >> E

これを次のように解析したい

(A >> (B >> (C >> (D >> E))))

私が理解していることから、Pythonではこの演算子は結合性のままなので、次のようになります。

((((A >> B) >> C) >> D) >> E)

演算子のオーバーロードを行うときに、Pythonで演算子のデフォルトの結合性を変更する方法はありますか?

4

2 に答える 2

4

これは可能です...しかし、少し手間がかかります。基本的な考え方は、右シフト演算子を使用して、実際の計算を延期する新しいタイプのオブジェクトを作成および更新することです。

たとえば、上記の変数A、B、C、D、およびEはすべてActual型のオブジェクトであるとします。Actualのインスタンスでrshift操作によって生成される新しいクラスDeferredを紹介します。Deferredは、オブジェクトを更新してそれ自体を返すrshift演算子も実装します。

(ところで、この回答の残りの部分では、A、B、C、D、およびEは不変であり、rshift操作によって新しいオブジェクトが生成されると想定しています。)

F = A >> B >> C >> D >> E

次のように計算されます...

F = Deferred(A,B) >> C >> D >> E
F = Deferred(A,B,C) >> D >> E
F = Deferred(A,B,C,D) >> E
F = Deferred(A,B,C,D,E)

Fは、逆のシーケンスから計算される、Actualのキャッシュされたインスタンスを維持します。さらに、FはActualと同じインターフェースを実装しているため、Deferredのインスタンスで呼び出されたメソッドは、Actualのキャッシュされたインスタンスに委任されます。

あなたが行っている計算の種類がわからないので、次の例では、延期された計算が実際に実行されるときにそれらが逆になることを示すために、ある種の些細なことを構成します。

class Var(object):
    def __init__(self):
        pass

    @property
    def name(self):
        return self._name( )

    @property
    def length(self):
        return len(self.name)


class Actual(Var):
    def __init__(self, name):
        Var.__init__(self)
        self._text = name

    def _name(self):
        return self._text

    def __rshift__(self, other):
        if isinstance(other, Actual):
            return Deferred(self, other)

        return len(self.name)

    @staticmethod
    def NewFromShiftComputation(sequence):
        x = ' >> '.join(reversed(map(lambda actual: actual.name, sequence)))
        return Actual(x)



class Deferred(Var):
    def __init__(self, *args):
        Var.__init__(self)

        self._items  = [ ]
        self._actual = None  #-- cached "actual"

        for item in args:
            self._items.append(item)

    def _name(self):
        self._assure_actual( )
        return self._actual.name

    def __rshift__(self, other):
        self._actual = None  #-- Invalidate the cached "actual"
        self._items.append(other)
        return self

    def _assure_actual(self):
        if self._actual is None:
            self._actual = Actual.NewFromShiftComputation(self._items)



A = Actual('A')
B = Actual('B')
C = Actual('C')
D = Actual('D')
E = Actual('E')

F = A >> B >> C >> D >> E

print F.name
print F.length
于 2012-05-08T04:53:03.907 に答える
1

これはオペレーターの問題ではありません。Pythonは左から右に評価します:http:
//docs.python.org/reference/expressions.html#evaluation-order

したがって、この場合はすべて同じ演算子なので、括弧が必要になります。

于 2012-05-08T01:01:49.053 に答える