2013-12-10 26 views
1

我有一些外部對象監聽/處理另一個對象的特徵。 如何獲取該對象特徵的偵聽器/處理程序列表?我有多個對象傾聽他人的特質,我希望能夠以某種方式進行查詢並確定哪些仍處於連接狀態。獲取特徵聽衆列表 - 誰在聽我的特質?

謝謝!

下面是一個使用Enthought性狀模塊的示例:

from traits.api import HasTraits,Str,Int,Float 

class GenerateEvents (HasTraits): 
    name = Str 
    age = Int 
    weight = Float 

class ListenEvents (HasTraits): 
    def _name_changed (self, object, name, old, new): 
     print "_name_changed:", object, name, old, new 

    def _age_changed (self, object, name, old, new): 
     print "_age_changed:", object, name, old, new 

    def _weight_changed (self, object, name, old, new): 
     print "_weight_changed:", object, name, old, new 

class AnotherListenEvents (HasTraits): 
    def _name_changed (self, object, name, old, new): 
     print "Another _name_changed:", object, name, old, new 

    def _age_changed (self, object, name, old, new): 
     print "another _age_changed:", object, name, old, new 

    def _weight_changed (self, object, name, old, new): 
     print "another _weight_changed:", object, name, old, new 

ge = GenerateEvents() 
le = ListenEvents() 
ale = AnotherListenEvents() 
ge.set(name = 'Joe', age = 22, weight = 152.0) 
ge.add_trait_listener(le) 
ge.add_trait_listener(ale) 
ge.set(name = 'Mike', age = 34, weight = 178.0) 

注意ge有兩個監聽器,leale。但是,由於ge我怎麼能找出聽衆是什麼?請注意,偵聽器可以在代碼中動態添加/刪除,因此它們不會被修復。

我希望澄清一下。

+0

什麼庫您使用?請展示一些示例或一個小例子來證明你的問題? –

回答

1

採取從enthought-dev郵件列表這個線程看看羅伯特·克恩的回答是: http://enthought-dev.117412.n3.nabble.com/How-do-I-find-the-listeners-for-a-trait-td1716192.html

這是你的代碼的修改版本,添加了用於檢索和顯示聽衆一對夫婦的功能。我添加了一個靜態偵聽器_age_changed,使用on_trait_change修飾器創建的偵聽器以及使用ge.on_trait_change(...)創建的偵聽器。

from traits.api import (HasTraits, Str, Int, Float, on_trait_change, 
         TraitChangeNotifyWrapper) 
from traits.trait_notifiers import StaticTraitChangeNotifyWrapper 


def get_listeners(h): 
    """ 
    h must be a HasTraits instance. 

    Returns a dictionary whose keys are trait names and whose values 
    are lists of notifiers. 
    """ 
    listeners = {} 
    for name in h.traits(): 
     notifiers = h.trait(name)._notifiers(0) 
     if notifiers is not None: 
      # Filter out the static listeners. Comment this out 
      # if you want to keep those. 
      notifiers = [notifier for notifier in notifiers 
          if not isinstance(notifier, StaticTraitChangeNotifyWrapper)] 
      listeners[name] = notifiers 
    return listeners 


def print_listeners(listeners): 
    """ 
    Print the dictionary of listeners returned by `get_listeners(h)`. 
    """ 
    for name, notifiers in listeners.items(): 
     print "trait '%s' has the following listeners:" % (name,) 
     for notifier in notifiers: 
      if notifier.name is None: 
       handler = notifier.handler 
       print " '%s' %r" % (handler.__name__, type(handler)) 
      else: 
       print " '%s' on object %s" % (notifier.name, notifier.object) 


class GenerateEvents (HasTraits): 
    name = Str 
    age = Int 
    weight = Float 

    def _age_changed(self, old): 
     print "age changed from ", old, "to", self.age 

    @on_trait_change('weight') 
    def do_something(self, obj, name, old, new): 
     print "do_something: name =", name 


class ListenEvents (HasTraits): 
    def _name_changed (self, object, name, old, new): 
     print "_name_changed:", object, name, old, new 

    def _age_changed (self, object, name, old, new): 
     print "_age_changed:", object, name, old, new 

    def _weight_changed (self, object, name, old, new): 
     print "_weight_changed:", object, name, old, new 


class AnotherListenEvents (HasTraits): 
    def _name_changed (self, object, name, old, new): 
     print "Another _name_changed:", object, name, old, new 

    def _age_changed (self, object, name, old, new): 
     print "another _age_changed:", object, name, old, new 

    def _weight_changed (self, object, name, old, new): 
     print "another _weight_changed:", object, name, old, new 


def printit(foo): 
    print foo 


ge = GenerateEvents() 
le = ListenEvents() 
ale = AnotherListenEvents() 
ge.set(name = 'Joe', age = 22, weight = 152.0) 
ge.add_trait_listener(le) 
ge.add_trait_listener(ale) 
ge.set(name = 'Mike', age = 34, weight = 178.0) 

# Make the function `printit` a listener to ge.name. 
ge.on_trait_change(printit, name='name') 

這裏是當你運行它,你(在IPython中)什麼:

In [103]: run trait_listeners_question 
age changed from 22 to 22 
do_something: name = weight 
age changed from 34 to 34 
_age_changed: <__main__.GenerateEvents object at 0x2680950> age 22 34 
another _age_changed: <__main__.GenerateEvents object at 0x2680950> age 22 34 
_name_changed: <__main__.GenerateEvents object at 0x2680950> name Joe Mike 
Another _name_changed: <__main__.GenerateEvents object at 0x2680950> name Joe Mike 
do_something: name = weight 
_weight_changed: <__main__.GenerateEvents object at 0x2680950> weight 152.0 178.0 
another _weight_changed: <__main__.GenerateEvents object at 0x2680950> weight 152.0 178.0 

In [104]: listeners = get_listeners(ge) 

In [105]: print_listeners(listeners) 
trait 'trait_added' has the following listeners: 
    '_trait_added_changed' on object <weakref at 0x2656d08; to 'ListenEvents' at 0x2680d70> 
    '_trait_added_changed' on object <weakref at 0x2656e68; to 'AnotherListenEvents' at 0x26808f0> 
trait 'age' has the following listeners: 
    '_age_changed' on object <weakref at 0x2656c58; to 'ListenEvents' at 0x2680d70> 
    '_age_changed' on object <weakref at 0x2656db8; to 'AnotherListenEvents' at 0x26808f0> 
trait 'ev' has the following listeners: 
    '_ev_changed' on object <weakref at 0x2656c00; to 'ListenEvents' at 0x2680d70> 
trait 'name' has the following listeners: 
    '_name_changed' on object <weakref at 0x2656cb0; to 'ListenEvents' at 0x2680d70> 
    '_name_changed' on object <weakref at 0x2656e10; to 'AnotherListenEvents' at 0x26808f0> 
    'printit' <type 'function'> 
trait 'weight' has the following listeners: 
    'do_something' on object <weakref at 0x2671368; to 'GenerateEvents' at 0x2680950> 
    '_weight_changed' on object <weakref at 0x2656ba8; to 'ListenEvents' at 0x2680d70> 
    '_weight_changed' on object <weakref at 0x2656d60; to 'AnotherListenEvents' at 0x26808f0> 
+0

如果我和一個特性事件'ev'到具有相應的'ev_changed'或'ev_fired'處理程序到'le'的'ge'對象,這不起作用。這是不可能使用這種技術? – reckoner

+0

我更新了代碼,所以它也返回'Event'特性。請注意,此版本還包含自動添加的「trait_added」事件特徵。 (另一個自動添加的特徵是'trait_modified',但在這種情況下,它的_notifiers(0)'調用返回None。) –