diff --git a/IPython/utils/tests/test_traitlets.py b/IPython/utils/tests/test_traitlets.py
index 79992a2..16baab7 100755
--- a/IPython/utils/tests/test_traitlets.py
+++ b/IPython/utils/tests/test_traitlets.py
@@ -129,6 +129,29 @@ class TestTraitType(TestCase):
         a = A()
         self.assertRaises(TraitError, A.tt.error, a, 10)
 
+    def test_dynamic_initializer(self):
+        class A(HasTraits):
+            x = Int(10)
+            def _x_default(self):
+                return 11
+        class B(A):
+            x = Int(20)
+        class C(A):
+            def _x_default(self):
+                return 21
+
+        a = A()
+        self.assertEquals(a._trait_values, {})
+        self.assertEquals(a.x, 11)
+        self.assertEquals(a._trait_values, {'x': 11})
+        b = B()
+        self.assertEquals(b._trait_values, {'x': 20})
+        self.assertEquals(b.x, 20)
+        c = C()
+        self.assertEquals(c._trait_values, {})
+        self.assertEquals(c.x, 21)
+        self.assertEquals(c._trait_values, {'x': 21})
+
 
 class TestHasTraitsMeta(TestCase):
 
diff --git a/IPython/utils/traitlets.py b/IPython/utils/traitlets.py
index 39c8570..a6bf9f8 100644
--- a/IPython/utils/traitlets.py
+++ b/IPython/utils/traitlets.py
@@ -248,9 +248,21 @@ class TraitType(object):
         default values must be delayed until the parent :class:`HasTraits`
         class has been instantiated.
         """
-        dv = self.get_default_value()
-        newdv = self._validate(obj, dv)
-        obj._trait_values[self.name] = newdv
+        # Check for a deferred initializer defined in the same class as the
+        # trait declaration or above.
+        mro = type(obj).mro()
+        meth_name = '_%s_default' % self.name
+        for cls in mro[:mro.index(self.this_class)+1]:
+            if meth_name in cls.__dict__:
+                break
+        else:
+            # We didn't find one. Do static initialization.
+            dv = self.get_default_value()
+            newdv = self._validate(obj, dv)
+            obj._trait_values[self.name] = newdv
+            return
+        # Complete the dynamic initialization.
+        self.dynamic_initializer = cls.__dict__[meth_name]
 
     def __get__(self, obj, cls=None):
         """Get the value of the trait by self.name for the instance.
@@ -265,7 +277,19 @@ class TraitType(object):
         else:
             try:
                 value = obj._trait_values[self.name]
-            except:
+            except KeyError:
+                # Check for a dynamic initializer.
+                if hasattr(self, 'dynamic_initializer'):
+                    value = self.dynamic_initializer(obj)
+                    # FIXME: Do we really validate here?
+                    value = self._validate(obj, value)
+                    obj._trait_values[self.name] = value
+                    return value
+                else:
+                    raise TraitError('Unexpected error in TraitType: '
+                        'both default value and dynamic initializer are '
+                        'absent.')
+            except Exception:
                 # HasTraits should call set_default_value to populate
                 # this.  So this should never be reached.
                 raise TraitError('Unexpected error in TraitType: '
@@ -294,6 +318,11 @@ class TraitType(object):
         else:
             return value
 
+    def set_dynamic_initializer(self, method):
+        """ Set the dynamic initializer method, if any.
+        """
+        self.dynamic_initializer = method
+
     def info(self):
         return self.info_text