我正在尝试创建一个带有多个参数的函数,并返回一个可调用的lambda函数。我将这些lambda函数传递给BeautifulSoup的find_all
方法以解析html。
这是我为生成lambda函数而编写的函数:
def tag_filter_function(self, name="", search_terms={}, attrs=[], **kwargs):
# filter attrs that are in the search_terms keys out of attrs
attrs = [attr for attr in attrs if attr not in search_terms.keys()]
# array of strings to compile into a lambda function
exec_strings = []
# add name search into exec_strings
if len(name) > 0:
tag_search_name = "tag.name == \"{}\"".format(name)
exec_strings.append(tag_search_name)
# add generic search terms into exec_strings
if len(search_terms) > 0:
tag_search_terms = ' and '.join(["tag.has_attr(\"{}\") and tag[\"{}\"] == \"{}\"".format(k, k, v) for k, v in search_terms.items()])
exec_strings.append(tag_search_terms)
# add generic has_attr calls into exec_strings
if len(attrs) > 0:
tag_search_attrs = ' and '.join(["tag.has_attr(\"{}\")".format(item) for item in attrs])
exec_strings.append(tag_search_attrs)
# function string
exec_string = "lambda tag: " + " and ".join(exec_strings)
return exec(compile(exec_string, '<string>', 'exec'))
从调用
返回的函数字符串tag_filter_function(name="article", search_terms={"id" : "article"})
是
lambda tag: tag.name == "article" and tag.has_attr("id") and tag["id"] == "article"
函数的返回值为None
。我不相信exec()
功能是我想在这里使用的功能,但我真的不确定。是否可以将此字符串转换为可执行的lambda函数,如果是这样的话?不确定我是否正确地采取了这种方式。
答案 0 :(得分:5)
绝对没有必要使用exec。要从函数返回函数,只需定义一个新函数并将其返回。 E.g。
def outer_function():
def inner_function():
something_here
return inner_function
在您的情况下,您似乎想要执行以下操作:
def tag_filter_function(self, name="", search_terms={}, attrs=[], **kwargs):
# filter attrs that are in the search_terms keys out of attrs
attrs = [attr for attr in attrs if attr not in search_terms.keys()]
def f(tag):
# add name search into exec_strings
if len(name) > 0:
if tag.name != name:
return False
# add generic search terms into exec_strings
if len(search_terms) > 0:
if not all(tag.has_attr(k) and tag[k] == v
for k, v in search_terms.items()):
return False
# add generic has_attr calls into exec_strings
if len(attrs) > 0:
if not all(tag.has_attr(item) for item in attrs):
return False
return True
return f
答案 1 :(得分:-2)
如果您想对代码进行最小的更改,可以尝试:
return eval(exec_string)
但是为了更好地解决问题,你应该遵循zvone的建议,并通过返回一个函数来完全重新制定方法。