我有一些外部对象正在侦听/处理另一个对象的特征。 如何获得该对象特征的侦听器/处理程序列表?我有多个对象听另一个人的特征,我希望能够以某种方式查询并确定哪些仍然连接。
谢谢!
以下是使用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
有两个听众,le
和ale
。但是,给定ge
我怎么能找出听众是什么?请注意,侦听器可以在代码中动态添加/删除,因此不会修复它们。
我希望澄清一点。
答案 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>