有没有办法避免 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.partial
或 lambda
)而不是它们的名称。例如:
['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
。
我有一个列表,定义如下:
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.partial
或 lambda
)而不是它们的名称。例如:
['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
。