Getting a default value on index out of range in Python

a = ['123', '2', 4]
b = a[4] or 'sss'
print b

I want to get a default value when the list index is out of range (here: 'sss').

How can I do this?

114490 次浏览

本着 Python 的“请求宽恕,而不是允许”的精神,这里有一个方法:

try:
b = a[4]
except IndexError:
b = 'sss'
try:
b = a[4]
except IndexError:
b = 'sss'

更干净的方法(只有当你使用的是 dict 时才有效) :

b = a.get(4,"sss") # exact same thing as above

下面是另一种你可能会喜欢的方式(同样,只适用于口头表达) :

b = a.setdefault(4,"sss") # if a[4] exists, returns that, otherwise sets a[4] to "sss" and returns "sss"

使用尝试/接球?

try:
b=a[4]
except IndexError:
b='sss'

本着“请求允许,而不是原谅”的非 Python 精神,这里有另一种方式:

b = a[4] if len(a) > 4 else 'sss'

您还可以为这些情况定义一个小的 helper 函数:

def default(x, e, y):
try:
return x()
except e:
return y

它返回函数 x的返回值,除非它引发 e类型的异常; 在这种情况下,它返回值 y。用法:

b = default(lambda: a[4], IndexError, 'sss')

编辑 : 使其只捕获一种指定类型的异常。

欢迎提出改进建议!

我完全赞成请求许可(也就是说,我不喜欢 try... except方法)。然而,当代码被封装在一个方法中时,它会变得更加干净:

def get_at(array, index, default):
if index < 0: index += len(array)
if index < 0: raise IndexError('list index out of range')
return array[index] if index < len(a) else default


b = get_at(a, 4, 'sss')

Since this is a top google hit, it's probably also worth mentioning that the standard "collections" package has a "defaultdict" which provides a more flexible solution to this problem.

你可以做一些整洁的事情,例如:

twodee = collections.defaultdict(dict)
twodee["the horizontal"]["the vertical"] = "we control"

阅读更多: http://docs.python.org/2/library/collections.html

您可以创建自己的列表类:

class MyList(list):
def get(self, index, default=None):
return self[index] if -len(self) <= index < len(self) else default

你可以这样使用它:

>>> l = MyList(['a', 'b', 'c'])
>>> l.get(1)
'b'
>>> l.get(9, 'no')
'no'

对于需要第一个元素的常见情况,可以执行

next(iter([1, 2, 3]), None)

我使用它来“打开”一个列表,可能是在过滤它之后。

next((x for x in [1, 3, 5] if x % 2 == 0), None)

或者

cur.execute("SELECT field FROM table")
next(cur.fetchone(), None)

在蟒蛇精神中美丽胜过丑陋

代码高尔夫方法,使用 slice 和 unpack (不确定这在4年前是否有效,但它是在 python 2.7 + 3.3中)

b, = a[4:5] or ['sss']

虽然比包装函式好,但是对于初学者来说有点吓人。

不拆包就切片:

b = a[4] if a[4:] else 'sss'

or, if you have to do this often, and don't mind making a dictionary

d = dict(enumerate(a))
b = d.get(4, 'sss')

另一种方式:

b = (a[4:]+['sss'])[0]

如果你正在寻找一种可维护的方法来获得索引操作符的默认值,我发现下面的方法很有用:

如果从操作符模块重写 operator.getitem以添加一个可选的默认参数,那么在保持向后兼容性的同时,您将获得与原始模块相同的行为。

def getitem(iterable, index, default=None):
import operator
try:
return operator.getitem(iterable, index)
except IndexError:
return default

如果您正在寻找一种快速减少代码长度的方法,您可以尝试这样做。

a=['123','2',4]
a.append('sss') #Default value
n=5 #Index you want to access
max_index=len(a)-1
b=a[min(max_index, n)]
print(b)

但是这个技巧只有在您不再需要对列表进行进一步修改时才有用