1

I have a function reference that is being called by an object. What I'd like is for that object to pass itself as a parameter to the function as it would normally do for its own functions.

IE I would like to use self.myFoo() instead of self.myFoo(self) in the following sample

Code Sample:

def foo(self):
    print(self.toString())

class Node:
    def __init__(self, myFoo):
        self.myFoo = myFoo

    def run(self):
        self.myFoo()

    def toString(self):
        return "Hello World"

n = Node(foo)
n.run()
Alter
  • 3,332
  • 4
  • 31
  • 56
  • Why are you trying to avoid `self.myFoo(self)`? – bmhkim Aug 31 '15 at 20:05
  • Nothing, mostly just curious as to why self.myFoo() doesn't work; also if I can make it work – Alter Aug 31 '15 at 20:06
  • The `self` in `def foo(self)` is misleading. I don't think that code runs. –  Aug 31 '15 at 20:07
  • it won't, you have to replace self.myFoo() with self.myFoo(self) for it to run – Alter Aug 31 '15 at 20:07
  • @vttran: The positional argument name `self` works, but you're right that it's misleading and not ideal. Similarly, you can rename a method's first argument to whatever you want, but 'self' is pretty standard. – bmhkim Aug 31 '15 at 20:08
  • @Alter: `self.myFoo()` doesn't work because you need to pass in an argument to fulfill the positional argument requirement. Your use of `self` as the argument for `foo` is misleading you, try changing the identifier to `obj` or `potato`. – bmhkim Aug 31 '15 at 20:10
  • I understand why it doesn't work. What I'm hoping for is some way to make it work – Alter Aug 31 '15 at 20:12

3 Answers3

4

The problem is that you assigned myFoo to an unbound function and are calling it as though it were bound. If you want to be able to use self.myFoo() you will need to curry the object into the first arg yourself.

from functools import partial

def foo(self):
    print(self.toString())

class Node:
    def __init__(self, myFoo):
        self.myFoo = partial(myFoo, self)

    def run(self):
        self.myFoo()

    def toString(self):
        return "Hello World"

n = Node(foo)
n.run()

Alternatively you could use

self.myFoo = types.MethodType(myFoo, self)

in your __init__(self, myFoo) method, but using partial is more commonly done, and more versatile since you can use it to curry arguments for any sort of function, not just methods.

Chad S.
  • 6,252
  • 15
  • 25
3

This thread looks like what you are looking for. To bound a method to an object (but not its class) at runtime you can do:

import types
n.foo = types.MethodType(foo, n)
Community
  • 1
  • 1
Quentin Roy
  • 7,677
  • 2
  • 32
  • 50
1

foo is a simple function. To make it callable via self.myFoo() you can attach it to the class - not the object. Even Node.myFoo is still an unbound function you can call it via self.myFoo() within your class.

def __init__(self, myFoo):
    Node.myFoo = myFoo
HelloWorld
  • 2,392
  • 3
  • 31
  • 68