Сохранение несвязанных функций python в объекте класса

Я пытаюсь сделать следующее в python:

В файле с именем 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

И затем в файле bar.py:   import foo

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

Однако я получаю следующую ошибку:

TypeError: unbound метод f() должен быть вызван с экземпляром данных в качестве первого аргумента (вместо этого используется int int)

Это справедливо, я полагаю, python рассматривает метод d.myFunction как метод класса. Тем не менее, я хочу, чтобы он рассматривал его как нормальную функцию, поэтому я могу назвать это, не добавляя неиспользуемый параметр "self" в определение myFunction.

Итак, вопрос:

Как сохранить функцию в объекте класса без привязки функции к этому классу?

Ответы

Ответ 1

data.fn = staticmethod(myFunction)

должен сделать трюк.

Ответ 2

Что вы можете сделать:

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

d.fn(1,2,3)

Это может быть не совсем то, что вы хотите, но работает.

Ответ 3

Это кажется мне бессмысленным. Почему бы просто не позвонить myFunction, когда вам это нужно?

В общем, в Python мы используем модули для такого рода пространств имен (сравним это с Java, где у вас просто нет выбора). И, конечно, myFunction уже привязан к пространству имен модулей, когда вы его определяете.

Это несколько обсуждается в ответах на этот вопрос.

Ответ 4

Спасибо Андре за ответ - так просто!

Для тех из вас, кого это касается, возможно, я должен был включить весь контекст проблемы. Здесь все равно:

В моем приложении пользователи могут писать плагины в python. Они должны определить функцию с четко определенным списком параметров, но я не хотел навязывать им какие-либо соглашения об именах.

Итак, пока пользователи пишут функцию с правильным количеством параметров и типов, все, что им нужно сделать, это что-то вроде этого (помните, что это код плагина):

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

Вызов setPluginFunction вызывает объект функции и устанавливает его в объект скрытого класса (вместе с другими связанными с плагинами элементами, этот пример несколько упрощен). Когда основное приложение хочет запустить эту функцию, я использую модуль runpy для запуска кода плагина, а затем извлекаю объект класса, упомянутый выше, - это дает мне данные конфигурации и функцию плагина, поэтому я могу выполнять ее чисто (без загрязняя мое пространство имен).

Весь этот процесс повторяется несколько раз для разных плагинов на одном и том же входе и, кажется, работает очень хорошо для меня.