3.1.4
Dynamic Handler Special Cases
In the one- and two-parameter signatures, the handler does
not receive enough information to distinguish between a change to the final
trait attribute being monitored, and a change to an intermediate object. In
this case, the notification dispatcher attempts to map a change to an
intermediate object to its effective change on the final trait attribute. This
mapping is only possible if all the intermediate objects are single values
(such as Instance or Any traits), and not List or Dict traits. If the change
involves a List or Dict, then the notification dispatcher raises a TraitError
when attempting to call a one- or two-parameter handler function, because it
cannot unambiguously resolve the effective value for the final trait attribute.
Zero-parameter signature handlers receive special
treatment if the final trait attribute is a List or Dict, and if the string
used for the names parameter is not just a simple
trait name. In this case, the handler is automatically called when the
membership of a final List or Dict trait is changed. This behavior can be
useful in cases where the handler needs to know only that some aspect of the
final trait has changed. For all other signatures, the handler function must be
explicitly set for the name_items
trait in order to called when the membership of the name
trait changes. (Note that the prefix+ and item[] syntaxes are both ways to specify both a trait
name and its _items variant.)
This behavior for zero-parameter handlers is not triggered for simple trait names, to preserve
compatibility with code written for versions of Traits prior to 3.0. Earlier
versions of Traits required handlers to be separately set for a trait and its
items, which would result in redundant notifications under the Traits 3.0
behavior. Earlier versions also did not support the extended trait name syntax,
accepting only simple trait names. Therefore, to use the “new style” behavior
of zero-parameter handlers, be sure to include some aspect of the extended
trait name syntax in the name specifier.
# list_notifier.py --- Example of zero-parameter handlers for
#
an object containing a list
from
enthought.traits.api import HasTraits, List
class
Employee: pass
class
Department( HasTraits ):
employees = List(Employee)
def
a_handler(): print "A handler"
def
b_handler(): print "B handler"
def
c_handler(): print "C handler"
fred =
Employee()
mary =
Employee()
donna =
Employee()
dept =
Department(employees=[fred, mary])
# "Old
style" name syntax
# a_handler
is called only if the list is replaced:
dept.on_trait_change(
a_handler, 'employees' )
# b_handler
is called if the membership of the list changes:
dept.on_trait_change(
b_handler, 'employees_items')
# "New
style" name syntax
# c_handler
is called if 'employees' or its membership change:
dept.on_trait_change(
c_handler, 'employees[]' )
print
"Changing list items"
dept.employees[1]
= donna # Calls B and C
print
"Replacing list"
dept.employees
= [donna] # Calls A and C
|