【问题标题】:Best practice for an optional return value可选返回值的最佳实践
【发布时间】:2021-10-27 10:22:58
【问题描述】:

假设一个函数不能计算一个有效的返回值。例如,字典查找可能无法找到键。当函数返回一个值或不返回值时,这种情况的最佳实践是什么?

1.返回None 比如dict.get()就是这种模式。这种方法的缺点是客户端需要检查返回值是否为None,并根据它做一些事情。

例如,

def getprice(car: Car) -> Optional[int]:
    if ispriceless(car):
        return None
    return car.value

def client():
    average_car_price_on_market = mean(
        [getprice(car) for car in get_all_cars() if getprice(car) is not None]
    )

(当然,我不必打两次getprice,但我只是想强调一下尴尬)

2。使用yield: 基本上这就像返回一个包含零个或一个元素的列表。上面的例子看起来像这样:

def getprice(car: Car) -> Generator[int, None, None]:
    if not ispriceless(car):
        yield car.value

def client():
    average_car_price_on_market = mean(
        [price for car in get_all_cars() for price in getprice(car)]
    )

我觉得这一篇更容易阅读,但有些人可能会说它不那么明确?

3.使用异常: 这可能是最明确的方法,但我想知道人们如何看待异常处理的开销;我还看到了反对使用异常作为控制流的论点(例如,here

【问题讨论】:

  • 这取决于您要达到的目标。如果您的程序可以处理无价的汽车,并且您希望平均价格不包括这些,那么过滤方法是合适的。还有,当汽车无价时,car.value 的价值是多少?如果该属性是None,您可以简化为[car.value for get_all_cars() if car.value]。如果属性不存在,则可以使用getattr(car, 'value', None)
  • 我会说没有批准的一般策略:这取决于上下文。

标签: python exception coding-style anti-patterns


【解决方案1】:

1.返回None 比如dict.get()就是这个模式。这种方法的缺点是客户端需要检查是否返回 value 是 None 并根据它做一些事情。

请注意,提到的.get 允许您指定应该为不存在的密钥提供什么。因此,如果您有能力获得元素 neutral w.r.t.进一步处理您可以跳过检查,例如,如果您想计算总数,您可能会这样做

data = {"A":100,"C":80}
total = sum(data.get(i,0) for i in ["A","B","C"])
print(total)

输出

180

【讨论】:

  • 是的,谢谢你提醒我。当然返回一个中性值(我不知道这是否是一个被广泛接受的术语)是一种选择。需要注意的是,适当的中性值取决于下游操作。
猜你喜欢
  • 2015-09-01
  • 2018-11-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-23
  • 1970-01-01
  • 1970-01-01
  • 2022-06-15
  • 1970-01-01
相关资源
最近更新 更多