【问题标题】:Python: Cleanest Way to Run Cascading Functions if Previous Function Returned NonePython:如果前一个函数返回无,则运行级联函数的最简洁方法
【发布时间】:2020-09-18 08:07:27
【问题描述】:

基本上,我有 3 个独立的功能。我想先运行geopy_parse,如果它返回None,那么我将运行libpostal_parse,如果返回None,我将最后运行最后一个函数google_maps_parse。函数的最终返回应该是最后运行的子函数的结果。我已经创建了一个函数来完成这个,但我想以一种更简洁、更 Pythonic 的方式重写它。

代码示例:

def parse_address(address_str):
    # if no address string provided, return None result
    if not address_str:
        return (None, None, None)
    
    # execute geopy parser
    res = geopy_parse(address_str)
    
    if not res:
        res = libpostal_parse(address_str)
    if not res:
        res = google_maps_parse(address_str)
    
    return {
        'nation': res['country'],
        'state': res['state'],
        'city': res['city'] or res['town'] or res['county']
        } 

【问题讨论】:

    标签: python function dictionary if-statement


    【解决方案1】:

    如何简化这方面的一个很好的提示是确定您有重复的代码。您还可以利用 python 支持一流函数的事实(即它们可以作为值/参数在其他地方传递)。

    编辑我刚刚看到您的更改。与一堆 if 语句相比,这种方法的一个好处是,如果您想添加更多解析器,它很容易扩展。

    def parse_address(address_str):
        # if no address string provided, return None result
        if not address_str:
            return (None, None, None)
        
        func_list = [geopy_parse, libpostal_parse, google_maps_parse]
    
        for func in func_list:
            res = func(address_str)
    
            # The return statement immediately breaks out of the loop
            # I.e. if the first func returns a non-None value, the others don't get executed
            if res is not None:
                return {
                    'nation': res['country'],
                    'state': res['state'],
                    'city': res['city'] or res['town'] or res['county']
                }
        else:
            # Handles the situation where all of your parsers return None
            return (None, None, None)
    

    【讨论】:

      【解决方案2】:

      假设 None 是您的函数唯一可能的虚假输出,您可以将它们视为布尔值并使用 or 进行回退,例如

      res = geopy_parse(address_str) or libpostal_parse(address_str) or google_maps_parse(address_str)
      

      将返回第一个非假结果。

      您也可以使用next() 以获得更大的灵活性,但这有点复杂,因为您必须在将可迭代对象提供给下一个(例如)之前过滤掉虚假值。

      res = next(filter(None, (
          fn(address_str)
          for fn in [geopy_parse, libpostal_parse, google_maps_parse]
      )), None) 
      

      filter(None, iterable) 等价于但比filter(lambda a: a, iterable) 更有效,它会从可迭代对象(惰性)中删除所有虚假项。

      所以这将函数作为输入,尝试将每个函数应用于输入,只保留真实的结果,然后返回第一个这样的结果(这就是 next() 所做的)。

      因为它只使用惰性构造(生成器和过滤器),所以它只在之前的函数都不合适时评估一个函数。

      【讨论】:

        猜你喜欢
        • 2022-12-10
        • 2023-03-28
        • 1970-01-01
        • 2017-05-20
        • 2016-10-27
        • 2016-12-25
        • 1970-01-01
        相关资源
        最近更新 更多