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

is there a way to avoid eval() to accomplish dynamic dispatch of a function specified in a list in 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])

有没有办法重组所有这些以避免评估? ast.literal_eval('a.'+element[3]) 抛出 'malformed string'

只需使用函数(当您需要预绑定参数时使用 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 上调用 方法 (可能带有参数),您可以使用基于 [=16 的其他方法=](方法名称为字符串),例如;但这种方法更通用。

有很多方法。考虑到您目前拥有的东西,最直接的可能是使用 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

就我个人而言,我可能倾向于重组这部分内容,并且可能还使用 中建议的 functools.partial