2013-12-10 27 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。) –