2012-05-08 48 views
3

我在寫一個python程序,我需要重載>>操作符。我面臨的問題是這個操作符需要正確的關聯。所以,如果我做了以下Python操作符重載和操作符關聯

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

我想這被解析爲

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

據我瞭解,在python這個操作符是左關聯的,所以我會得到,

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

有沒有辦法在運算符重載時改變python中運算符的默認關聯性?

+0

我可能是錯的,但是這不是一個運算符重載的問題,但更多隻是標準的「操作順序」?如果他們都是相同的運營商,那麼它會從左到右評估從左到右 – jdi

+0

重載<<運營商intead;) – wim

+0

@wim我想到了,哈哈。對於習慣於從左向右閱讀的人來說,這樣做會更自然。我也想過重=運算符,因爲我認爲這是正確的聯想,但這隻會是非常難看。 – martega

回答

2

這可以做...但它需要一點努力。基本思想是使用右移運算符來創建和更新一個新類型的對象,這個對象將延遲實際的計算。例如,假設上面的變量:A,B,C,D和E都是Actual類型的對象。我們將介紹一個由實例的實例上的rshift操作產生的新類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維護一個實際的緩存實例,它是從反向序列計算出來的。此外,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 
1

這不是操作員的問題。 Python從左到右評估:
http://docs.python.org/reference/expressions.html#evaluation-order

因此,在這種情況下,因爲它的所有操作符都是括號的,所以需要括號。

+0

我很害怕這個。我只是希望有一些方法可以告訴Python解釋器在某些情況下改變運算符的關聯性。 – martega

+0

@martega:如果你可以改變interp的規則,可能會破壞你正在使用的其他庫。爲什麼不製作一個將它們作爲參數並運行正確順序的函數呢? – jdi