Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass a class method as an argument to a function external to that class?

This is how it works for me:

class SomeName:
  def __init__(self):
    self.value = "something"
  def some_method(self):
    print self.value

def external_func(instance, method):
  method(instance)

external_func(SomeName(), SomeName.some_method)

This appears to work correctly. Is this the right way to do this?

like image 660
AturSams Avatar asked Jul 15 '15 11:07

AturSams


3 Answers

Your code is "technically correct" (it does what you ask for) but - at least in your example - pretty useless:

def external_func(instance, method):
  method(instance)

external_func(SomeName(), SomeName.some_method)

is the same as:

def external_func(method):
  method()

external_func(SomeName().some_method)

which FWIW is the same as:

SomeName().some_method()

but I assume you understood this already .

Now you probably have a reason to try to pass both the method AND instance to external_func(), or there might be a better way to solve your real problem...

like image 95
bruno desthuilliers Avatar answered Oct 21 '22 22:10

bruno desthuilliers


Depending on what you're doing. Because functions are also objects in Python it is possible to do so.

But is it a good solution? It seems though that you're trying to handle a problem which maybe could be better solved with more of an object oriented approach:

class A:
    def __init__(self):
        self.value = "class A"
    def some_method(self):
        print self.value

class B:
    def __init__(self):
        self.value = "class B"
    def some_method(self):
        print self.value

some_class = A()
some_class.some_method()

some_class = B()
some_class.some_method()

Output:

"class A"
"class B"

In my view this would be a better approach (if this is possible/reasonable in your case): You just call some_method() on your class, maybe without even knowing what exact type of object you're dealing with (regarding inheritance). The class itself knows what to do and reacts accordingly when its method has been called.

This of course doesn't work when you work with external libraries which you have no influence on.

like image 45
adrianus Avatar answered Oct 21 '22 22:10

adrianus


I of course don't know what you're doing exactly, but it sounds to me like you're trying to do too much inside of one function. Your problem might be better solved by simply splitting up the contents of external_func.

The goals here, as I understand them, are you don't know ahead of time what the object/method pair will be, and want to reduce code repetition.

Perhaps something like this would be better:

def main():
    obj = SomeName()
    # do the setting up portion 
    complex_object = external_func_set_up(obj)
    # presumably at some point you have to designate the method to be used:
    method = get_method_name(obj) 
    # run the method:
    getattr(obj, method)()
    # finish up the external operation: 
    external_func_complete(***args***) 

I understand this is more code, but I think in the end it's a lot clearer what is happening, and also might force you to think through your problem a bit more (and potentially come up with an even better solution).

like image 39
Rick supports Monica Avatar answered Oct 21 '22 21:10

Rick supports Monica