b10hazard
b10hazard

Reputation: 7809

error passing a class method as an argument to another class method

I'm attempting to pass a class method as an argument to another class method. Below is an example...

import time

class MyClass(object):

    def doSomething(self,argument2,argument3):
        print argument2,argument3

    def attemptTenTimes(self,fun,*args):
        attempt = 0
        while True:
            try:
                print 'Number of arguments: %s' % len(*args)
                print args
                output = fun(*args)
                return output
            except Exception as e:
                print 'Exception: %s' % e
                attempt += 1
                time.sleep(10)
                if attempt >= 10: return
                else: continue

MC = MyClass()
MC.attemptTenTimes(MC.doSomething,(MC,'argument2','argument3',))

The output is....

Number of arguments: 3
((<__main__.MyClass object at 0x7f7e6be4e390>, 'argument2', 'argument3'),)
Exception: doSomething() takes exactly 3 arguments (2 given)
Number of arguments: 3
((<__main__.MyClass object at 0x7f7e6be4e390>, 'argument2', 'argument3'),)
Exception: doSomething() takes exactly 3 arguments (2 given)
Number of arguments: 3
((<__main__.MyClass object at 0x7f7e6be4e390>, 'argument2', 'argument3'),)
Exception: doSomething() takes exactly 3 arguments (2 given).............

I am passing three arguments to the function doSomething, however, this exception keeps coming up. I've used functions as arguments to other functions before, but this is my first time doing it within the context of a class. Any help would be appreciated. Thanks.

Upvotes: 0

Views: 90

Answers (1)

Henry Keiter
Henry Keiter

Reputation: 17168

You've not passed three arguments; you passed two. You need this:

MC.attemptTenTimes(MC.doSomething,*('argument2','argument3'))

or this (equivalent):

MC.attemptTenTimes(MC.doSomething,'argument2','argument3')

The attemptTenTimes function has the parameter *args, which collects positional arguments into a tuple referred to locally as args. You're passing it the whole tuple as the only positional argument, so locally you have a variable named args that looks like ((MC,'argument2','argument3'),). As a result, when you unpack it and pass it to your function, you're just passing the inner tuple.

As an aside, you also shouldn't be unpacking args when you pass it to len, because that'll throw an error. You just want len(args) on line 12 up there.

Alternately, you could change your attemptTenTimes function signature to this:

def attemptTenTimes(self,fun,args):

You could then pass the whole args tuple to it, as you were originally doing. I believe using *args is more standard, though, and personally I think it's clearer.

Upvotes: 1

Related Questions