18

I'm trying to do the following in python:

In a file called foo.py:

# simple function that does something:
def myFunction(a,b,c):
  print "call to myFunction:",a,b,c

# class used to store some data:
class data:
  fn = None

# assign function to the class for storage.
data.fn = myFunction

And then in a file called bar.py: import foo

d = foo.data
d.fn(1,2,3)

However, I get the following error:

TypeError: unbound method f() must be called with data instance as first argument (got int instance instead)

This is fair enough I suppose - python is treating d.myFunction as a class method. However, I want it to treat it as a normal function - so I can call it without having to add an unused 'self' parameter to the myFunction definition.

So the question is:

How can I store a function in a class object without the function becoming bound to that class?

3
  • I think you intended to use: d.fn(1,2,3) and not d.myFunctions(1,2,3) Commented Nov 29, 2008 at 13:35
  • yes, i think you meant d.fn() Commented Nov 29, 2008 at 13:44
  • 1
    The solution is below, but why would you want this? Commented Nov 29, 2008 at 20:26

3 Answers 3

27
data.fn = staticmethod(myFunction)

should do the trick.

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

1 Comment

This is the correct answer and syntax, since the function is defined elsewhere.
1

What you can do is:

d = foo.data()
d.fn = myFunction

d.fn(1,2,3)

Which may not be exactly what you want, but does work.

Comments

0

Thanks to Andre for the answer - so simple!

For those of you who care, perhaps I should have included the entire context of the problem. Here it is anyway:

In my application, users are able to write plugins in python. They must define a function with a well-defined parameter list, but I didn't want to impose any naming conventions on them.

So, as long as users write a function with the correct number of parameters and types, all they have to do is something like this (remember, this is the plugin code):

# this is my custom code - all plugins are called with a modified sys.path, so this
# imports some magic python code that defines the functions used below.
from specialPluginHelperModule import *

# define the function that does all the work in this plugin:
def mySpecialFn(paramA, paramB, paramC):
    # do some work here with the parameters above:
    pass

# set the above function:
setPluginFunction(mySpecialFn)

The call to setPluginFunction takes the function object and sets it in a hidden class object (along with other plugin-configuration related stuff, this example has been simplified somewhat). When the main application wants to run the function, I use the runpy module to run the plugin code, and then extract the class object mentioned above - this gives me the configuration data and the plugin function so I can run it cleanly (without polluting my namespace).

This entire process is repeated multiple times for different plugins over the same input, and seems to work very well for me.

2 Comments

"all plugins are called with a modified sys.path" Are you modifying the sys.path temporarily in a try/finally block or is there a way to "shadow" the global sys.path?
Please use the edit link on your question to add additional information. The Post Answer button should be used only for complete answers to the question.

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.