Traits User Manual
Previous: 3.1.3 Notification Handler Signatures Table of Contents Next: 3.2 Static Notification
Traits User Manual
1 Introduction
1.1 What Are Traits?
1.2 Background
2 Defining Traits: Initialization and Validation
2.1 Predefined Traits
2.1.1 Predefined Traits for Simple Types
2.1.2 Other Predefined Traits
2.2 Trait Metadata
2.2.1 Internal Metadata Attributes
2.2.2 Recognized Metadata Attributes
2.2.3 Accessing Metadata Attributes
3 Trait Notification
3.1 Dynamic Notification
3.1.1 Example of a Dynamic Notification Handler
3.1.2 The name Parameter
3.1.3 Notification Handler Signatures
3.1.4 Dynamic Handler Special Cases
3.2 Static Notification
3.2.1 Handler Decorator
3.2.2 Specially-named Notification Handlers
3.2.3 Attribute-specific Handler Signatures
3.2.4 General Static Handler Signatures
3.3 Trait Events
3.4 Undefined Object
4 Deferring Trait Definitions
4.1 DelegatesTo
4.2 PrototypedFrom
4.3 Keyword Parameters
4.3.1 Prefix Keyword
4.3.2 Listenable Keyword
4.4 Notification with Deferring
5 Custom Traits
5.1 Trait Subclassing
5.1.1 Defining a Trait Type
5.1.2 Defining a Trait Property
5.1.3 Other TraitType Members
5.2 The Trait() Factory Function
5.2.1 Trait () Parameters
5.2.2 Mapped Traits
5.3 Trait Handlers
5.3.1 TraitPrefixList
5.3.2 TraitPrefixMap
5.4 Custom Trait Handlers
5.4.1 Example Custom Trait Handler
6 Advanced Topics
6.1 Initialization and Validation Revisited
6.1.1 Dynamic Initialization
6.1.2 Overriding Default Values in a Subclass
6.1.3 Reusing Trait Definitions
6.1.4 Trait Attribute Definition Strategies
6.1.5 Type-Checked Methods
6.2 Interfaces
6.2.1 Defining an Interface
6.2.2 Implementing an Interface
6.2.3 Using Interfaces
6.3 Adaptation
6.3.1 Defining Adapters
6.3.2 Using Adapters
6.3.3 Controlling Adaptation
6.4 Property Traits
6.4.1 Property Factory Function
6.4.2 Caching a Property Value
6.5 Persistence
6.5.1 Pickling HasTraits Objects
6.5.2 Predefined Transient Traits
6.5.3 Overriding __getstate__()
6.5.4 Unpickling HasTraits Objects
6.5.5 Overriding __setstate__()
6.6 Useful Methods on HasTraits
6.6.1 add_trait()
6.6.2 clone_traits()
6.6.3 set()
6.6.4 add_class_trait()
6.7 Performance Considerations of Traits

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

Previous: 3.1.3 Notification Handler Signatures Table of Contents Next: 3.2 Static Notification
Traits User Manual