引言

在使用强化学习或者其他神经网络进行参数调整时,有时候我们进场需要对其中的一些参数进行设置检测,来验证设置是否满足要求,这时就不免会进行很多次调试。如果我们仅仅通过在每次实验时改变变量的一些元素,很可能会弄得很乱,如何让自己的代码看起来整洁,优雅呢?今天我们针对函数指针进行讲解。

如在一个现实的例子中,我们需要对强化学习的状态进行设置,在这里设置了几组不同的状态表示,想分别进行测试。如果在传统的方法中,我们可能会这样:

        torque_mod = math.sqrt(pow(self.torque[0],2)+pow(self.torque[1],2)+pow(self.torque[2],2))
        force_mod = math.sqrt(pow(self.force[0],2)+pow(self.force[1],2)+pow(self.force[2],2))
        torque_tmp = np.array(self.torque)/torque_mod
        force_tmp = np.array(self.force)/force_mod
        self.state = np.append(np.abs(torque_tmp),np.abs(force_tmp)).reshape(1,6)
#         self.state = np.append(np.abs(self.torque),np.abs(force_tmp)).reshape(1,6)
#         self.state = np.append(np.abs(torque_tmp),np.abs(self.force)).reshape(1,6)

将本次实验要测试的样本放在程序中,对其他代码进行注释。当代码或者测试的样本少的时候是可行的,但是一旦需要测试的数据变多,这种方法就没有任何优势了。

函数指针

函数指针,顾名思义,就是取函数的地址,将其作为指针进行使用。而函数的地址,其实就是函数名,如在下面的代码中:

def func():
    a = 1
    return a
c = func
print(c())
print(c)

当我们运行以后,会得到什么结果呢?

在这里,将func其实就是这个函数的函数指针,将其赋值给c,就是将函数的地址赋值给c。然后运行c(),就是相当于c语言中的*p中取地址的内容的意思了,不过这里对应的是运行地址对应的函数。

他的作用和下面的代码是一样的:

def func():
    a = 1
    return a
c = func()
print(c)

但是不同的是,使用这种方法的c,已经是函数func经过运行后的结果了,换句话说,我们不能通过对c操作,来改变func函数中的变量。而函数指针是可以的。

这样做就可以让我们实现:将函数单独定义,并定义好接口,当需要某种函数功能时,只需要将函数地址赋值给需要操作的变量,然后对需要操作的变量进行操作就可以。可以通过配合字典实现方便得函数调用。

应用

还是在上面的例子中,我们首先在另一个文件中定义需要得测试样本的函数:

然后在这文件所在的字典变量中定义一个键:

这样我们就获取了这个函数的函数地址,最后在我们需要的地方进行调用:

        self.state_fun = params['state_fun']       
        state = self.state_fun(torque_tmp, force_tmp, self.torque, self.force,self.position[2])

这样以后,我们在测试样本的时候,就只需要在字典中,将我们想要测试的那一组函数名放进字典的'state_cun'对应的值中就可以了,大大优化了代码表示。

May the force be with you!