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



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

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()']
]

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

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

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

只需使用函数(当您需要预先绑定参数时,使用 functools.partiallambda)而不是它们的名称。 例如:

['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的方法(方法名称作为字符串),例如;但这种方法更通用。

有很多方法。 鉴于您目前拥有的内容,最直接的可能是使用 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)

在这里,我element[4]中隐藏了论点(如果有的话),以提供'0' lstrip

就我个人而言,我可能倾向于重组这一点,并且可能也像亚历克斯·马泰利(Alex Martelli)的回答中所建议的那样使用functools.partial

最新更新