2011-05-24 65 views
2

我想包裝一個非traits模型類,用於Python Traits。我的目標是編寫一個基於Traits的用戶界面來操作「外部」模型類。外部模型類已由SWIG生成,因此我不能將enthought.traits.api.HasTraits添加爲祖先(我認爲,雖然我可能是錯的)。如何包裝非Traits模型以用於Python Traits?

我目前最好的嘗試是

from enthought.traits.api import HasStrictTraits, Property, Instance 

class ExternalModel(): 
    foo = 'foo' 

class TraitsModel(HasStrictTraits): 
    _e = Instance(ExternalModel) 

    def __init__(self): 
     self._e = ExternalModel() 
     self.add_trait('foo', Property(lambda  :getattr(self._e,'foo' ), 
             lambda attr:setattr(self._e,'foo',attr))) 

從而導致性狀類爲主TraitsModel有一個可變的財產委託給包含非性狀ExternalModel實例。但是,TraitsModel.trait_names()不會將'foo'報告爲公認的特徵。

有關如何讓TraitsModel報告鏈接到ExternalModel的'foo'特徵的任何建議? enthought.traits.api.DelegatesTo似乎要求目標是一個Traits類(儘管我可能沒有找到正確的調用,這是可能的)。

更多的MVC-ish方法可能會有一個基於特徵的我的ExternalModel視圖。我一直無法弄清楚基於特徵視圖的非Traits模型。在這方面的建議也非常受歡迎。

更新我已經想出瞭如何使用http://agentzlerich.blogspot.com/2011_05_01_archive.html的方法將HasTraits作爲ExternalModel超類,它似乎完全浪費了時間。顯然,SWIG伏都教和特質不道德的人不會動搖。在TraitsModel中包裝ExternalModel,因爲這個問題似乎是最好的路線。

回答

2
from enthought.traits.api import HasStrictTraits, Instance, Property 

class ExternalModel(object): 
    foo = 'foo' 

class TraitsModel(HasStrictTraits): 
    _e = Instance(ExternalModel, ExternalModel()) 

    def __init__(self): 
     ''' 
     >>> wrapper = TraitsModel() 
     >>> wrapper.foo 
     'foo' 
     >>> wrapper._e.foo = 'bar' 
     >>> wrapper.foo 
     'bar' 
     >>> wrapper.trait_names() 
     ['trait_added', '_e', 'foo', 'trait_modified'] 
     ''' 
     HasStrictTraits.__init__(self) 
     for trait in (name for name in dir(self._e) if not name.startswith('__')): 
      self.__class__.add_class_trait(
       trait, 
       Property(
        lambda:getattr(self._e, trait), 
        lambda attr:setattr(self._e, trait, attr) 
       ) 
      ) 


if __name__ == '__main__': 
    import doctest 
    doctest.testmod() 

一個相當健壯的解決方案是使用HasTraits類的add_class_trait,加上dir(self._e)得到的ExternalModel屬性和一個發電機的表達/列表解析的名稱來過濾魔類方法名(具有適當函數的filter將更好地包裝更復雜的類)。

另外:

  • ExternalModel應繼承object

  • __init__應該調用HasStrictTraits.__init__(或super(HasStrictTraits, self).__init__()

  • _e也可以在實例性狀聲明創建作爲第二個參數使用ExternalModel()或甚至(),或作爲方法TraitsModel喜歡的:

    def __e_default(self): # note preceding underscore 
        return ExternalModel() 
    

最後,我有一個slightly old copy of the Enthought APIs including Traits它可以非常方便。

+2

可以在'foo'上使用這種技術'on_trait_change'。這樣,您可以監視外部對象中的更改。這可能嗎? – reckoner 2013-09-24 19:48:51

+0

上面的剪切〜幾乎可以工作,但是在swig導出的類中,當我調用wrapper.configure_traits()打開配置gui時,對象只是指向swig對象的指針;那裏仍然需要一些映射。 – 2016-04-26 16:17:09

+0

此外,「traits.api」模塊最近需要被「enthought」不合格使用。 – 2016-04-26 16:18:11

相關問題