Instantiating a default instance for an Enthought trait

Question:

Consider this simple minimal example:

from traits.api import Instance, Str, HasTraits

class Person(HasTraits):
    name = Str("hooked")

class Chair(HasTraits):
    sitting = Instance(Person)

t = Chair()
print t.sitting.name

This fails since t.sitting evaluates to None. Enthought’s traits module will enforce that the type of t.sitting is a Person but how can I get the default person to instantiate here? I don’t want to pass any parameters to the Chair(**kwargs) I’d like this to be done automatically. The expected output to the print statement is hooked.

Asked By: Hooked

||

Answers:

This is interesting. According to the Instance docstring, calling Instance will return None if klass is a class and arg and kw are not specified. arg and kw have default values of None and so calling Instance(Person) is returning None like you are seeing.
I got your code to work by adding “kw = {}” or “args = []” to the Instance call.

from traits.api import Instance, Str, HasTraits

class Person(HasTraits):
    name = Str("hooked")

class Chair(HasTraits):
    sitting = Instance(Person, kw = {})

t = Chair()
print t.sitting.name

This prints “hooked” as expected.

Answered By: J. Corson

You’ve explicitly defined Chair so that its default instance does not instantiate its attribute sitting, and that’s what is happening. If you’d rather instantiate sitting by default, then you can.

So take your pick. If you want to keep your original definition of Chair, but this time ensure that sitting is instantiated to its default, then:

from traits.api import Instance, Str, HasTraits

class Person(HasTraits):
    name = Str("hooked")

class Chair(HasTraits):
    sitting = Instance(Person)

t = Chair(sitting=Person())
print t.sitting.name

But if you’d rather that a default Chair always be instantiated with a default sitting, then (EDIT: and showing traitsui in action):

from traits.api import Instance, Str, HasTraits
from traitsui.api import Item, View

class Person(HasTraits):
    name = Str("hooked")

class Chair(HasTraits):
    sitting = Instance(Person,())
    view = View((Item( 'sitting', style = 'custom')))

t = Chair()
print t.sitting.name
t.configure_traits()

# or overridden by:
w = Chair(sitting=Person(name='snooked'))
print w.sitting.name
Answered By: Jonathan March

Another way of doing this is to create a method in your Chair class that instantiates a default instance of your Person class. This method name takes the form of ‘_name_default’ where name is your trait attribute. This method is called when Chair is instantiated. For reference see this page in the Traits documentation.

See the code example below which I have tested in v5.1.2 and v6.2.0.

from traits.api import Instance, Str, HasTraits

class Person(HasTraits):
    name = Str("hooked")

class Chair(HasTraits):
   sitting = Instance(Person)

def _sitting_default(self):
    #Instantiate your class here
    return Person()

t = Chair()
print(t.sitting.name)
Answered By: John Otter
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.