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
.
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.
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
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)
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
.
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.
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
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)