views:

471

answers:

4

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?

+6  A: 
data.fn = staticmethod(myFunction)

should do the trick.

André
This is the correct answer and syntax, since the function is defined elsewhere.
ΤΖΩΤΖΙΟΥ
A: 

This seems pointless to me. Why not just call myFunction when you need it?

In general, in Python, we use modules for this kind of namespacing (contrast this with Java where you just have no choice). And of course, myFunction is already bound to the module namespace when you define it.

It is discussed somewhat in the answers to this question.

Ali A
I guess so you could attach a particular function to an object, and then have it called by the object without caring which of several functions it is actually calling.
Matthew Schinckel
Misunderstood what the OP was doing, didn't notice it was a class-method not an instance-method.
Matthew Schinckel
A: 

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.

Matthew Schinckel
A: 

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.

Thomi
"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?
haridsv