2012-03-02 70 views
1

當您給開發者一個「robs_numbers」對象時,開發人員可以按照他們想要的任何順序調用各種過濾器, obj.filter1()。filter2()。filtern()..什麼是訂購調用對象方法的最pythonic方式,沒有

但是,通常我篩選出的數字越早,過濾速度就越快。

我希望開發人員能夠以他們想要的任何順序調用filter()方法。 開發人員然後獲取一個robs_numbers對象(或者可能是一個可迭代的..)。 但是我希望我的方法(過濾器)按照priority()給出的順序實際運行。

從技術上講,priority()應該採用pair filter:[args],以便我可以使用任何過濾器。那麼優先級()將返回的優先級值

下面是一些示例代碼,雖然你可能完全改變,如果它是更Python對象:

from random import randint 
data = [randint(0,100) for i in range(100)] 

class robs_numbers(): 
    def __init__(self,numbers,_min,_max): 
     self.numbers = iter(numbers) 
     self._min = _min #approx 
     self._max = _max #approx 

    def bigger(self,x): 
     print "priority = ", self.priority(x) 
     return robs_numbers([i for i in self.numbers if i>x],x,self._max) 

    def smaller(self,x): 
     print "priority = ", self.priority(x) 
     return robs_numbers([i for i in self.numbers if i<x],self._min,x) 

    def order(self,backwards=False): 
     print "priority = ", self.priority() 
     self.numbers = iter(sorted(self.numbers,reverse=backwards)) 
     return self 

    # ... 
    # More filter methods 
    # ... 

    def priority(self,x=None): 
     #works out the order methods should be called to increase efficiency 
     if x is None: 
      return 99999 
     else: 
      return abs(x-(self._max-self._min)/2) 

和例如兩個有效的用途,但我想他們兩個要快,現在只有一個是有效的:

def get(): 
    return robs_numbers(data,0,100) 

rf = get().bigger(80).smaller(90).order() #faster in this order 
print list(rf.numbers), rf._min, rf._max 

#priority = 30 
#priority = 80 
#priority = 99999 
#[81, 81, 82, 83, 85, 86, 87, 87, 89] 80 90 


rf = get().order().smaller(90).bigger(80) #slower in this order 
print list(rf.numbers), rf._min, rf._max 
#priority = 99999 
#priority = 40 
#priority = 35 
#[81, 81, 82, 83, 85, 86, 87, 87, 89] 80 90 

回答

1

你必須創建某種懶洋洋地評估查詢組,每當開發者調用list()或其他什麼東西,需要你只執行所有的過濾器導出數據到另一個對象。 Django在他們的查詢集中有一個很好的例子,which are lazy

所以,你可以寫東西的

class RobsNumbers(object): 
    def __init__(self, numbers, min, max): 
     self._numbers = numbers 
     self._min = min 
     self._max = max 
     self._filters = [] 

    def bigger(self, x): 
     new_obj = RobsNumbers(self._numbers, x, self._max) 
     new_obj._filters = self._filters + [GreaterThanFilter(x)] 
     return new_obj 

    # Other filter methods simply add a filter to the _filters list of the object 

    def __iter__(self): 
     # Here is the complicated optimization logic to reorder and execute the filters 
     pass 

注意,大意是這個代碼零過濾,直到開發者請求包含在RobsNumbers對象裏面的數據,所以它是很懶惰。

+0

謝謝,這看起來相當簡單。我現在只是仰望「懶惰」。即使他們在添加更多過濾器之前消費了itertools.islice(),它也可能仍然有效; p – 2012-03-02 06:11:57

相關問題