1

I want to have a class with dynamic methods.

From these arrays:

prefix = ['android','iphone','blackberry'] 
method = ['AddToPush','DelFromPush','GetPushMessages']

I want to create a class like:

class MobileManager(object)

    def __init__(self):
        self.mobileLib = MobileLib()

    def androidAddToPush(self, args):
        self.mobileLib.AddToPush(args, 'android')

    def iphoneAddToPush(self, args):
        self.mobileLib.AddToPush(args, 'iphone')    

    def blackberryAddToPush(self, args):
        self.mobileLib.AddToPush(args, 'blackberry') 

   [...]

How can I have these methods generated/created at runtime?

UpAndAdam
  • 4,515
  • 3
  • 28
  • 46
Rafał Kot
  • 1,064
  • 3
  • 15
  • 26

3 Answers3

1

If your set of prefixes/methods is defined at init time, you can try something like this:

class MobileManager(object):
    def __init__(self):
        for prefix_name in prefix:
            for method_name in method:
                func = lambda self, args: getattr(self.mobileLib, method_name)(args, prefix)
                full_method_name = "%s%s" % (prefix, method_name)
                setattr(self, full_method_name, func)
        ...

If your dynamic methods get more complicated, the lambda will soon be limited, though.

Jonathan Ballet
  • 973
  • 9
  • 21
  • Will it work like this: self.mobileLib.method_name(args, prefix) ? – Rafał Kot Dec 30 '11 at 09:19
  • In Your code You have line: func = lambda self, args: self.mobileLib.AddToPush(args, prefix) 'AddToPush' should be from method array. – Rafał Kot Dec 30 '11 at 09:28
  • It won't work: 1. drop `self` from `func()` parameters (you bind it to a concrete instance, not a class). 2. all `func` will use the last value of `method_name`. [You don't want that](http://stackoverflow.com/q/139819/4279). – jfs Dec 30 '11 at 09:39
  • 1
    `setattr(self, prefix+method_name, make_func(getattr(self.mobileLib, method_name), prefix))` should fix it, where `make_func = lambda func, prefix: lambda args: func(args, prefix)` – jfs Dec 30 '11 at 10:04
  • This one is working! `make_func = lambda func, prefix_name: lambda args: func(args, prefix_name) setattr(self, prefix_name+method_name, make_func(getattr(self.mobileLib, method_name), prefix_name))` *Thanks a lot!* – Rafał Kot Dec 30 '11 at 10:29
0

Or why not inherate

class MobileManager(object)

    def __init__(self):
        self.mobileLib = MobileLib()

    def AddToPush(self, args, platform=None):
        self.mobileLib.AddToPush(args, platform)

class Android(MobileManager):
    def __init__(self):
        MobileManager.__init__(self)

    def AddToPush(self, args):
         MobileManager.AddToPush(args, platform="android")
Jakob Bowyer
  • 33,878
  • 8
  • 76
  • 91
0

Dynamic methods are often the wrong approach leading to confusing code.

Here, I'd do this:

class Mobile(object):
    def add_to_push(self, args):
        ....
    def del_from_push(self, args):
        ...
    def get_push_methods(self, args):
        ...

And in your Manager:

class MobileManager(object):
    def __init__(self):
        self.android = Mobile()
        self.blackberry = Mobile()
        self.iphone = Mobile()

Now, instead of manager.mobileLib.add_to_push(args, 'android'), you would write manager.android.add_to_push(args).

You can even dispatch dynamically if you have a platform variable: getattr(manager, platform).add_to_push(args).

If you want different behaviour for the 3 types of platform you can make subclasses of Mobile (perhaps AndroidMobile, BlackberryMobile and IPhoneMobile).

When a new platform appears (perhaps windows7) it's obvious how to change the code to support it.