获取特质听众列表 - 谁在听我的特质?

时间:2013-12-10 21:32:29

标签: python enthought traits

我有一些外部对象正在侦听/处理另一个对象的特征。 如何获得该对象特征的侦听器/处理程序列表?我有多个对象听另一个人的特征,我希望能够以某种方式查询并确定哪些仍然连接。

谢谢!

以下是使用Enthought Traits模块的示例:

 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我怎么能找出听众是什么?请注意,侦听器可以在代码中动态添加/删除,因此不会修复它们。

我希望澄清一点。

1 个答案:

答案 0 :(得分:1)

从enthought-dev邮件列表中查看Robert Kern在这个帖子中的答案: 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>