说明
总结了一下上篇的内容,并将链条的机制补全。
内容
1 整体结构
整体上可以分成三部分:主线、次线和参数线。
主线是逻辑主体的主体:
- 1 假设数据框已经ready,主线从数据框里获取所需的数据并进行处理
- 2 主线在执行前,先执行次线,来对数据框进行筛选
主线蕴含了项目分解的元数据,以及worker进行工作的元数据,是蓝图与实施的连接点。
次线是某次执行中的关键元数据,其中ruleresult甚至会单独存储,与主数据对应。次线检查了程序的运行状态,以及规则的逻辑状态。
最后是参数线。参数线是可扁平化的字典(或为空),目前是手工指定,将来会使用算法自动调参。
2 流程处理的定义
还是按照之前的例子,对数据先执行is_str_len_0
, 判断字符长度是否有效;然后执行str2half_width
,对字符长度有效的数据进行全半角转换。这是最简单的链条,只有两个节点,描述是比较符合语言习惯的。正常的处理流程会比较长,至少会有10个,那么从原理上,仍然可以语言描述;但是从实际上,基本无法描述。
当规则超过10个,描述起来人脑是很难容纳的
这也是做这种函数链的意义,因为每次我们只需要考虑上一步和这一步。就算有多个依赖,那么一般也不会有很多。有需要还可以分散到多步。关键是要确保相邻的两个步骤高度清晰,高度可靠,这样每次就可以站在前面的点,继续向后延展。这看起来很像动态规划,保持动态规划不崩的要点是每一步都很踏实。
run_chain有了chain_funcname_list
和chain_funcname_dict
之后,就可以执行函数链了。
chain_funcname_list = ['is_str_len_0','str2half_width']
chain_funcname_dict = {
}
# chain的调试
# step1
is_str_len_0_dict = {
}
is_str_len_0_dict['subline_dict'] = None
is_str_len_0_dict['main_dict'] = {
'key_id':'id',
'depend_cols':['content'],
'input_cols': ['some_str']}
is_str_len_0_dict['para_dict'] = None
# step2:如果依赖某条规则,但无视规则的结果,那么就是{'some_rule':None}
str2half_width_dict = {
}
str2half_width_dict['subline_dict'] ={
'is_str_len_0':0}
str2half_width_dict['main_dict'] = {
'key_id':'id',
'depend_cols':['content'],
'input_cols': ['some_str']}
str2half_width_dict['para_dict'] = None
chain_funcname_dict['is_str_len_0'] = is_str_len_0_dict
chain_funcname_dict['str2half_width'] = str2half_width_dict
结合最近做的前端工作(交互式表格),一旦开发完成,那么将通过前端进行配置和修改。
3 pre_process
因为筛选的前序相对麻烦一点,所以独立出来:
- 1 当没有依赖的规则(火车头),那么数据(根据选择的列)和id全部透传
- 2 当依赖规则正常运行,但是不依赖结果,那么根据规则的状态筛选
- 3 既依赖规则正常运行,又依赖运行结果的,那么就和2的结果取and。规则的筛选是比较复杂的,使用向量的比对。
# 次线处理
def pre_process(self,subline_dict = None, main_dict = None):
key_id = main_dict['key_id']
depend_cols = main_dict['depend_cols'