user3267989
user3267989

Reputation: 329

Calling Class methods

I have 3 classes defined this way:

class Device:
    Some method

class SSH:
    def connect(self,type):
    # code
    def execute(self,cmd):
    # code

class Netconf:
    def connect(self,type):
    # code
    def execute(self,cmd):
    # code

Note SSH and Netconf classes have same method names but they do things differently. I have an instance of class Device and would like to access methods like this-

d = Device()
d.connect('cli') # <-- This should call SSH method and subsequently
                 # d.execute(cmd) should call execute method from SSH class
                 # too.
d.connect('netconf') # <-- This should call Netconf method and subsequently
                     # d.execute(cmd) should call execute method from
                     # Netconf class too.

The question is - how do I make it happen? I want to be able to use methods of SSH/Netconf class on Device class instance 'd' based on the input.

Upvotes: 0

Views: 175

Answers (2)

martineau
martineau

Reputation: 123541

You can do this by storing the type of device connected in a private Device attribute and then forwarding most method calls to it by adding a custom __getattr__() method. This is a little tricky in the connect() method because that's were the target device is defined (as opposed to in the Device.__init__() initializer).

I also changed the variable you had named type to kind to avoid colliding with the built-in module of the same name.

class Device(object):
    def connect(self, kind):
        if kind == 'cli':
            target = self._target = SSH()
        elif kind == 'netconf':
            target = self._target = Netconf()
        else:
            raise ValueError('Unknown device {!r}'.format(kind))
        return target.connect(kind)

    def __getattr__(self, name):
        return getattr(self._target, name)

class SSH(object):
    def connect(self, kind):
        print('SSH.connect called with kind {!r}'.format(kind))
    def execute(self, cmd):
        print('SSH.execute called with cmd {!r}'.format(cmd))

class Netconf(object):
    def connect(self, kind):
        print('Netconf.connect called with kind {!r}'.format(kind))
    def execute(self, cmd):
        print('Netconf.execute called with cmd {!r}'.format(cmd))

d = Device()
d.connect('cli')
d.execute('cmd1')
d.connect('netconf')
d.execute('cmd2')

Output:

SSH.connect called with kind 'cli'
SSH.execute called with cmd 'cmd1'
Netconf.connect called with kind 'netconf'
Netconf.execute called with cmd 'cmd2'

Upvotes: 1

Ignacio Vazquez-Abrams
Ignacio Vazquez-Abrams

Reputation: 799310

You should implement the Strategy Pattern. The connect() method should instantiate the appropriate class (detach()ing from the previous if required) and store it, and then other methods should delegate to the stored object.

Upvotes: 0

Related Questions