代码之家  ›  专栏  ›  技术社区  ›  CodeNoob

一种更有效的使用if条件的pythonic方法

  •  1
  • CodeNoob  · 技术社区  · 7 年前

    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
    

    这很难理解(在我看来),所以我想知道是否有人可以建议一些更具蟒蛇风格的短线?例如,我可以合并这两个for循环吗?如果我合并两个for循环,会消耗更多的时间吗?

    3 回复  |  直到 7 年前
        1
  •  2
  •   Ma0    7 年前

    它更紧凑 短路 由于 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 包含两者 肯定词 if s将影响结果。这不是好做法。
        2
  •  2
  •   MSeifert    7 年前

    这很难理解(在我看来),所以我想知道是否有人可以建议一些更具蟒蛇风格的短线?

    # 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

    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)
    

        3
  •  1
  •   tobias_k    7 年前

    除了使用 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 到a 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()) ,尤其是那些已经 设置 具有快速查找的结构。