12

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?

4
  • 4
    You could just pass SomeName().some_method then call method(), it is also not really a class method as you are calling it with an instance Commented Jul 15, 2015 at 11:48
  • 1
    @PadraicCunningham I think OP probably just means "a class's method", not a classmethod. Commented Jul 15, 2015 at 11:59
  • But it needs to be able to call it with data that will be computed later. There is some function foo(), were all the steps are the same except the method used to do (for instance) some tax computation which depends on the region or something (my goal is to prevent code duplication). Commented Jul 15, 2015 at 12:01
  • @zehelvion, not sure what the difference is, you can call the method and pass whatever you like, maybe add more context to your question if there is something you feel might be an issue Commented Jul 15, 2015 at 12:05

4 Answers 4

9

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...

Sign up to request clarification or add additional context in comments.

2 Comments

oh, in the real case, the function needs to construct and preform some lengthy computation with the class instance, using one of it's specific method.
My use-case is to be able to pass the method without the instance to avoid circular imports...
1

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).

Comments

0

You could pass SomeName().some_method or make some_metod staticmethod or classmethod if there is no instance data used in your method.

Check documentation to know more about staticmethod and classmethod:

2 Comments

It is not a static method, it has a self argument and depends on the value attribute of the example class. It is therefore not static by definition.
You're correct, but as I see the value is constant, hence it's possible to define it as a class property, hence it's possible to use classmethod.
0

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.

4 Comments

In my case the class itself is the same and familiar with two (or more) behaviors but the situation changes. Imagine this, a Dog class that can bite, bark or growl depending on what the owner decides. We need to pass the behavior the owner desires to some dog which isn't born yet. The dog allocation / computation process is always the same but the behavior is an argument. The dog is computed based on some data provided.
As we try to model classes accordingly to real world objects, it would be kind of odd to ask an unborn dog to bark, isn't it? Is there no way to wait until the dog has been created before you decide to tell it what to do?
I'm starting to think this is right. There is a model (instance) and a context, was the model needs to behave. Imagine a person in a formal business and the same person in a rock concert. The function / script, gets the input to generate the person instance and the situation (appropriate behavior). It is used to determine the result of the derived instance with the specified behavior.
@wolfdawn wery late comment but anyway: what you describe above looks like the strategy pattern.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.