关于python:将函数指定为对象的属性,然后在没有隐含的“自我”争论的情况下调用?

Assigning functions as attributes of an object, then calling without the implied 'self' arguement?

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

1
2
3
4
5
def fish_slap(fish):
    # do something

class dance(object):
    dance_move=fish_slap

但是,如果我们试着说

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

我们得到GET以下错误

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

Python似乎将此视为一个对象方法,并提供了隐含的"self"参数。公平地说,我刚刚了解到,以这种方式将函数指定为属性等同于直接在类中定义函数。我可以看到这是一个有用的特性。

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

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

其中scipy被导入为sp。这些目标函数在单个.py文件中定义,并在整个代码中使用,并且自然作为独立函数存在,而不是作为带有隐含"self"参数的类方法存在。

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

1
2
3
4
5
6
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
2
class dance(object):
    dance_move=staticmethod(fish_slap)

注意,如果要分配给实例的属性,则不需要使用staticmethod

1
2
3
4
5
6
7
8
9
10
11
12
>>> 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!