我有这段代码检查条件:
def is_important(data_row):
if data_row.get('important', None):
return True
add_data = get_additional_data(data_row)
for word in NEGATIVE_WORDS:
if word in add_data.lower():
return False
for word in POSITIVE_WORDS:
if word in add_data.lower():
return True
return False
这很难遵循(在我看来),所以我想知道是否有人可以用更短的线条建议更多的pythonic?我可以将两个for循环合并吗?如果我合并两个for循环,它会消耗更多时间吗?
答案 0 :(得分:2)
由于any
很像你的显式循环,它更紧凑,短路。
def is_important(data_row):
if data_row.get('important', None):
return True
add_data = get_additional_data(data_row)
if any(word in add_data.lower() for word in NEGATIVE_WORDS): # negative check takes precedence.
return False
if any(word in add_data.lower() for word in POSITIVE_WORDS):
return True
return False
关于这一点的几件事:
.lower()
而不是NEGATIVE_WORDS
时拨打POSITIVE_WORDS
?add_data
同时包含NEGATIVE_WORDS
和POSITIVE_WORDS
,则最后两个if
的顺序将影响结果。这不是一个好习惯。答案 1 :(得分:2)
这很难遵循(在我看来),所以我想知道是否有人可以用更短的线条建议更多的pythonic?
通常pythonic并不意味着更短的线条。 Pythonic代码应该易于阅读和遵循(至少有一点背景)。因此,如果您发现难以阅读,您可以将其纳入不同的功能:
# I'm not sure if the function name is a good fit, it's just a suggestion.
def contains_at_least_one(data, words):
for word in words:
if word in data:
return True
return False
def is_important(data_row):
if data_row.get('important', None):
return True
add_data = get_additional_data(data_row).lower()
if contains_at_least_one(add_data, NEGATIVE_WORDS):
return False
if contains_at_least_one(add_data, POSITIVE_WORDS):
return True
return False
我可以将两个for循环合并吗?
不是真的。因为NEGATIVE_WORDS
循环应优先于POSITIVE_WORDS
循环(至少在您的代码中)。除非你的意思是将其分解为函数。然后先看看。
如果我合并两个for循环,它会消耗更多时间吗?
我不确定你的意思是什么"合并"循环,但如果你想缩短它,你可以在上面的方法中使用any
。它相当于for
- 循环和更短 - 但是,根据我和StefanPochmans的基准测试,速度较慢:
def contains_at_least_one(data, words):
return any(word in data for word in words)
def is_important(data_row):
if data_row.get('important', None):
return True
add_data = get_additional_data(data_row).lower()
if contains_at_least_one(add_data, NEGATIVE_WORDS):
return False
if contains_at_least_one(add_data, POSITIVE_WORDS):
return True
return False
您甚至可以使用and
return
来减少行数。我不推荐它,因为这样的结构不会提高可读性,但这是你的决定,它是缩短"的一种方式。代码:
def is_important(data_row):
if data_row.get('important', None):
return True
add_data = get_additional_data(data_row).lower()
return (not contains_at_least_one(add_data, NEGATIVE_WORDS) and
contains_at_least_one(add_data, POSITIVE_WORDS))
有点牵强,但也许你甚至可以用set
来加快速度。这将要求您只查找整个单词匹配(不是部分匹配,而不是多字匹配):
def contains_at_least_one(data, words):
return data.intersection(words)
def is_important(data_row):
if data_row.get('important', None):
return True
add_data = set(get_additional_data(data_row).lower().split()) # set and split!
return not contains_at_least_one(add_data, NEGATIVE_WORDS) and contains_at_least_one(add_data, POSITIVE_WORDS)
如果您不想要标点符号来破坏匹配,请参阅tobias_k答案中的正则表达式建议。然而,设定的方法仅仅意味着"小建议" - 我怀疑它可以适用于你的情况。但是你需要判断它。
答案 2 :(得分:1)
除了使用any
之外,你还可以将不同的条件组合成一个return
语句,不过这是否更明确可能是一个意见问题。
def is_important(data_row):
add_data = get_additional_data(data_row)
return (data_row.get('important', None)
or (not any(word in add_data.lower() for word in NEGATIVE_WORDS)
and any(word in add_data for word in POSITIVE_WORDS)))
虽然如果get_additional_data
费用昂贵,您可以先将if
分开。
此外,您可以先将add_data
转换为set
个(小写)字词来加快检查速度,但这会略微改变逻辑,因为不匹配单词片段。
def is_important(data_row):
add_data = set((word.lower() for word in get_additional_data(data_row).split()))
return (data_row.get('important', None)
or (not any(word in add_data for word in NEGATIVE_WORDS)
and any(word in add_data for word in POSITIVE_WORDS)))
或者,使用例如.split()
而不是re.findall(r"\w+")
。 any(word in POSITIVE_WORDS for word in add_data.split())
找到没有标点符号的单词。
根据正面和负面列表的大小,也可能需要付清以反转支票,例如set
,特别是如果这些已经def validate_number(s):
try:
return float(s)
except (ValueError, TypeError):
return s
data = [validate_number(s) for s in data]
具有快速查找的结构。