2017-07-28 31 views
1

在python 3.x中,我試圖實現一個類,該類將作爲參數給出的序列的代理。該代理還使用在輸入序列的每個元素上調用的函數。代理類可以是可索引或可迭代的序列

代理類根據輸入序列中的可用性動態實現__getitem____iter____len__方法的正確方法是什麼?這是我在做這個(我打電話給我的序列「供應商」,功能是「改造」)的嘗試:

class TransformProviderProxy: 

    def __init__(self, input_provider, transform): 
     self.input_provider = input_provider 
     self.transform = transform 

    def __iter__(self): 
     # Use generator expressions to produce a new iterator when requested 
     return (self.transform(data_sample) for data_sample in self.input_provider) 

    def __getattr__(self, name): 
     if name == "__getitem__" and hasattr(self.input_provider, "__getitem__"): 
      return self._getitem_impl 
     elif name == "__len__" and hasattr(self.input_provider, "__len__"): 
      return self._len_impl 
     else: 
      return None 

    def _getitem_impl(self, index): 
     return self.transform(self.input_provider[index]) 

    def _len_impl(self): 
     return len(self.input_provider) 

但是失敗,因爲它似乎是蟒蛇尋找__getitem__時繞過__getattr__。什麼是正確的方法來做到這一點?

作爲獎勵,有沒有辦法做到這一點,而我的代理類動態地從collections.abc.Sequencecollections.abc.Iterable繼承取決於輸入序列?

PS:我也考慮過只是在實現__getitem__時,依靠捕獲TypeError來嘗試在非可索引輸入序列上調用它時,但我希望能夠通過查找來檢查我的代理類是否可索引__getitem__的存在,而不必使用索引顯式調用它。

回答

0

只實施__getitem____len__。這將失敗,並顯示相應的錯誤消息,如果input_provider沒有實現這些操作:

class TransformProviderProxy: 

    def __init__(self, input_provider, transform): 
     self.input_provider = input_provider 
     self.transform = transform 

    def __iter__(self): 
     # Use generator expressions to produce a new iterator when requested 
     return (self.transform(data_sample) for data_sample in self.input_provider) 

    def __getitem__(self, index): 
     return self.transform(self.input_provider[index]) 

    def __len__(self): 
     return len(self.input_provider) 

正如例如:

>>> t = TransformProviderProxy(2, lambda x: x+2) 
>>> t[1] 
TypeError: 'int' object is not subscriptable 

>>> t = TransformProviderProxy([1,2,3,4], lambda x: x+2) 
>>> t[1] 
4 
+0

我編輯我的問題,你發佈之前你的答案很抱歉(你太對我來說很快!)。我曾考慮過這個問題,但我希望能夠檢查我的類是否可以索引(理想情況是通過檢查它是否是'collections.abc.Sequence'的一個實例),而不必明確嘗試索引它。也許我應該接受你的方式是更pythonic的方式? –

+0

是的,[EAFP(容易請求寬恕而不是權限)](https://docs.python.org/3/glossary.html#term-eafp)被認爲比[LBYL(在你跳躍之前看)更「pythonic」 ](https://docs.python.org/3/glossary.html#term-lbyl)。不過,您可能需要簽出第三方模塊['wrapt',它是'ObjectProxy'](http://wrapt.readthedocs.io/en/latest/wrappers.html#proxies-and-wrappers)。這可能包含一些(已建成的)解決方案,以解決您的緊急問題。對不起,我沒有看到你之前的最後一段...... :( – MSeifert