Arun Kaliraja Baskaran
Arun Kaliraja Baskaran

Reputation: 1086

How to observe Instance member variables using traitlets library?

I am trying to use the traitlets library provided by ipython in my code. Suppose if a trait is of instance of a particular class how do i observe change in value for a member of the class..

example:

class A:
    def init(self,val):
    self.value = val

class myApp(HasTraits):
    myA = Instance(A,kw={'val':2})

I want to have an observe method to be called if 'value' member variable of object myA is changed.. SOmething like below:

@observe('myA.value')
def onValueChange(self,change):
    return

is it possible with the trailets implementation?

Upvotes: 3

Views: 1828

Answers (1)

Oluwafemi Sule
Oluwafemi Sule

Reputation: 38982

In order to observe changes to the value of an instance trait, the class for the instance trait should subclass Hastraits.

traitlets.observe(*names, **kwargs)

A decorator which can be used to observe Traits on a class.

from traitlets import HasTraits, observe, Instance, Int
​
class A(HasTraits):
    value = Int()
​
    def __init__(self, val):
        self.value = val
    
    @observe('value')
    def func(self, change):
        print(change)
​
class App(HasTraits):
    myA = Instance(klass=A, args=(2,))
​

app = App()
app.myA.value = 1

{'name': 'value', 'old': 0, 'new': 2, 'owner': <__main__.A object at 0x10b0698d0>, 'type': 'change'}
{'name': 'value', 'old': 2, 'new': 1, 'owner': <__main__.A object at 0x10b0698d0>, 'type': 'change'}

Edit

To keep the change handler in the composed class, you can dynamically set an observer.

Note that, the attribute observed must be property of a trait. In case you don't have access to modify class A to subclass HasTraits, you may be able to compose a class that subclasses HasTraits on the fly using some type magic.

from traitlets import HasTraits, observe, Instance, Int

class A(HasTraits):
    value = Int()

    def __init__(self, val):
        self.value = val

class App(HasTraits):
    myA = Instance(klass=A, args=(2,))
    
    def __init__(self):
        super().__init__()
        self.set_notifiers()
        
    def set_notifiers(self):
        HasTraits.observe(self.myA, func, 'value')
        
    
    def func(self, change):
        print(change)
        
app = App()

app.myA.value = 1

Upvotes: 6

Related Questions