有没有办法避免eval()完成在python中列表中指定的函数的动态调度

时间:2015-01-27 04:13:11

标签: python eval

我有一个如下定义的列表:

header_fields = [
['delim',0,4,'strip()'],
['qual',4,5,None],
['NLS_CODE',6,25,'strip()'],
['source_system_id',26,45,'strip()'],
['extract_name',46,65,'strip()'],
['extract_serial_number',66,85,'strip()'],
['file_counter',86,88,"lstrip('0')"],
['total_file_count',89,91,'strip()'],
['extract_run_date_time',92,126,'strip()'],
['from_date',127,161,'strip()'],
['thru_date',162,196,'strip()'],
['number_of_rows',197,216,'strip()'],
['data_recons1',217,246,'strip()'],
['data_recons2',247,276,'strip()'],
['data_recons3',277,306,'strip()']
]

元素[1]和元素[2]用于解析名为header的行 我想为header_fields中的每个元素调用元素[3],如下所示:

for element in header_fields:
    a = header[element[1]:element[2]]
    if element[3] None:
        b = a
    else:
        b = eval('a.'+element[3])

有没有办法重组所有这些以避免评估? ast.literal_eval('a.'+element[3])抛出'格式错误的字符串'

2 个答案:

答案 0 :(得分:4)

只需使用函数(当需要预绑定参数时使用functools.partiallambda)而不是名称。 E.g:

['delim',0,4,str.strip],
['qual',4,5,None],
['NLS_CODE',6,25,str.strip],
['source_system_id',26,45,str.strip],
['extract_name',46,65,str.strip],
['extract_serial_number',66,85,str.strip],
['file_counter',86,88, lambda s: s.lstrip('0')],
... etc ...

然后,您当前正在尝试

b = eval('a.'+element[3])

使用,而不是

b = element[3](a)

如果您确定知道您总是想在a上调用方法(可能带参数),您可以使用基于getattr的其他方法(以方法名称作为字符串),例如;但这种方法更为通用。

答案 1 :(得分:4)

有很多方法。考虑到目前的情况,最直截了当的可能就是使用getattr

header_fields = [
['delim',0,4,'strip'],
['qual',4,5,None],
['NLS_CODE',6,25,'strip'],
['source_system_id',26,45,'strip'],
['extract_name',46,65,'strip'],
['extract_serial_number',66,85,'strip'],
['file_counter',86,88,'lstrip', ('0',)],
['total_file_count',89,91,'strip'],
['extract_run_date_time',92,126,'strip'],
['from_date',127,161,'strip'],
['thru_date',162,196,'strip'],
['number_of_rows',197,216,'strip'],
['data_recons1',217,246,'strip'],
['data_recons2',247,276,'strip'],
['data_recons3',277,306,'strip']
]

然后:

for element in header_fields:
    a = header[element[1]:element[2]]
    if element[3] is None:
        b = a
    else:
        args = element[4] if len(element) > 3 else ()
        b = getattr(a, element[3])(args)

在这里,我在[{1}}中隐藏了论据,以便element[4]提供'0'

就我个人而言,我可能会倾向于重组一些,也可能按Alex Martelli's answer中的建议使用lstrip