Python 中赋值默认值的优雅方法

16 投票
6 回答
4385 浏览
提问于 2025-04-17 07:23

考虑这一行代码:

some_value = lst.attr[idx]

这里可能有两个错误,attr 可能不存在,idx 可能超出了范围。

有没有什么优雅的方法来简化这个表达?理想情况下,想要变成这样:

some_value = lst.attr[idx] or default_value

(别在家里尝试。这只适用于那些正确定义的表达式,能够计算出某种结果。)

当然,我可以这样做:

try:
    some_value = lst.attr[idx]
except:
    some_value = default_value

但是如果我是在赋值的情况下呢?比如:

print [x.attr[idx] for x in y]

在这种情况下,处理错误并赋予默认值的“pythonic”方式是什么?

6 个回答

3

写一个函数,让它聪明点:

def get_attr_with_index_and_default(obj, attr_name, index, default):
    try:
        return getattr(obj, attr_name)[index]
    except (AttributeError, IndexError):
         return default

print [get_attr_with_index_and_default(x, 'attr', idx, some_default) for x in y]

如果你能控制 x 的类,你可以把这个当作一个方法来用,或者把它改成一个描述符。但我觉得这样做不太值得,因为会导致代码变得晦涩难懂,还可能出现难以追踪的错误。

4

在这种情况下,处理错误和赋予默认值的“Pythonic”方式是什么呢?

>>> import this
...
Explicit is better than implicit.
...
Sparse is better than dense.
Readability counts.
...
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.

我觉得“Pythonic”赋予默认值的方式,要么是处理异常,正如你在问题中提到的,要么就是自己写获取值的方法。

6

你需要先搞清楚你想要达到什么目的。这里提到的“错误”这个词可能会让人误解。

如果你是想处理传给你函数的对象类型不对的情况,那你就不应该处理这个问题,而是应该抛出一个异常。

如果你想让你的函数能够处理多种不同类型的对象,那这其实并不算错误,使用一个默认值可能是合理的选择。

最简单的办法是先检查一下这个属性是否存在。例如:

if hasattr(lst, "attr"):
    attr = lst.attr
else:
    attr = {}

我假设 lst.attr 是一个字典,这样你可以像下面这样处理默认值:

lst.attr.get(idx, default_value)

千万不要使用 try/except 语句而不明确说明你要捕获什么异常。这样可能会掩盖掉更多你不想处理的问题。

在你最后的代码中,我觉得不应该试图用一行代码解决问题。代码的可读性很重要。我对下面的代码不太满意,但如果把 xyattr 替换成更具描述性的名字,那就会更好。

attrs = [(x.attr if hasattr(x) else {}) for x in y]

print [attr.get(idx, default_value) for attr in attrs]

撰写回答