将函数指定为对象的属性,然后在没有隐含的“self”参数的情况下调用?

时间:2013-02-24 21:36:05

标签: python

Python允许您将预定义的函数作为属性分配给类,例如

def fish_slap(fish):
    # do something

class dance(object):
    dance_move=fish_slap

但是,如果我们试着说

d=dance()
d.dance_move("Halibut")

我们得到以下错误

TypeError: fish_slap() takes exactly 1 arguement (2 given)

Python似乎将此视为对象方法并提供隐含的“自我”参数。很公平,似乎我刚刚学会了以这种方式将函数作为属性赋值等同于直接在类中定义函数。我可以看到这是一个有用的功能。

然而,在这种情况下,这不是我想要的。在我的应用程序中,我将统计模型编码为不同的类,它们也有自己的“训练”方法,用于根据提供的数据训练模型参数。为此,您希望最小化(或最大化)需要提供的值的目标函数。一个简单的目标函数示例是

def RMSE(predicted,observed):
    "Root mean squared error"
    return sp.sqrt(sp.mean((predicted-observed)**2))

其中SciPy已作为sp导入。这些目标函数在单个.py文件中定义并在我的代码中使用,并且自然地作为独立函数存在,而不是作为具有隐含的“self”参数的类方法。

我希望能够将所需的目标函数设置为属性,以便模型对象执行的任何后续工作都可以使用该函数,例如

some_model=SomeModel(initial_parameter_values_guess) 
some_model.objective_function = RMSE
some_model.train(training_data)
predictions_RMSE = some_model.predict()
some_mode.objective_function = MAE
predictions_MAE = some_model.predict()

在这个示例中似乎我可以将目标函数作为参数传递给训练,但是在我的应用程序中有更多人想要做的事情,似乎更有意义的是能够设置/获取客观函数而非反复提供它作为论证。

有许多解决方法可以实现这种基本行为,但最流行的方法是什么?

请注意,我当前的代码是python2和python3兼容的。如果有特定版本的解决方案,请指出。我正在使用python2运行以便能够使用matplotlib但是我正在尝试确保代码与该模块之外的python3兼容。

1 个答案:

答案 0 :(得分:8)

您可以使用staticmethod

class dance(object):
    dance_move=staticmethod(fish_slap)

请注意,如果您要分配实例的属性,则无需使用staticmethod

>>> def move():
...     print "disco party!"
... 
>>> class dance(object):
...     dance_move = staticmethod(move)
... 
>>> d = dance()
>>> d.dance_move()
disco party!
>>> d.break_it_down = move
>>> d.break_it_down()
disco party!