我刚开始使用Python。
如果列表在1
之前包含布尔True
对象,如何从列表中获取整数1
的索引?
>>> lst = [True, False, 1, 3]
>>> lst.index(1)
0
>>> lst.index(True)
0
>>> lst.index(0)
1
我认为Python在0
方法的参数中将False
视为1
而True
视为index
。如何获得整数1
的索引(即2
)?
在列表中以这种方式处理布尔对象的原因是什么? 从解决方案来看,我可以看出它并不那么简单。
答案 0 :(得分:13)
列表是可变序列,通常用于存储集合 同质物品(其中精确的相似程度会因此而异 应用程序)。
您不应将异构数据存储在列表中。
list.index
的实施仅使用Py_EQ
(==
运算符)执行比较。在您的情况下,比较返回真值,因为True
和False
分别具有整数1和0的值(毕竟the bool class is a subclass of int)。
但是,您可以使用生成器表达式和built-in next
function(从生成器获取第一个值),如下所示:
In [4]: next(i for i, x in enumerate(lst) if not isinstance(x, bool) and x == 1)
Out[4]: 2
在比较x
到1之前,我们会检查bool
是否为x
的实例。
请注意,next
可以引发StopIteration
,在这种情况下,可能需要(重新)引发ValueError
(以模仿list.index
的行为)
将此全部包装在一个函数中:
def index_same_type(it, val):
gen = (i for i, x in enumerate(it) if type(x) is type(val) and x == val)
try:
return next(gen)
except StopIteration:
raise ValueError('{!r} is not in iterable'.format(val)) from None
一些例子:
In [34]: index_same_type(lst, 1)
Out[34]: 2
In [35]: index_same_type(lst, True)
Out[35]: 0
In [37]: index_same_type(lst, 42)
ValueError: 42 is not in iterable
答案 1 :(得分:8)
Booleans 是整数的Python,这就是为什么你可以像任何整数一样使用它们:
>>> 1 + True
2
>>> [1][False]
1
[这并不意味着你应该:)]
这是因为bool
是int
的子类,并且几乎总是布尔值的行为就像0或1(除非它被转换为字符串 - 你会得到{ {1}}和"False"
代替。)
还有一个想法是如何实现您想要的(但是,尝试重新考虑您的逻辑,并考虑上述信息):
"True"
此代码重新定义了>>> class force_int(int):
... def __eq__(self, other):
... return int(self) == other and not isinstance(other, bool)
...
>>> force_int(1) == True
False
>>> lst.index(force_int(1))
2
方法,该方法用于比较int
方法中的元素,以忽略布尔值。
答案 2 :(得分:5)
>>> zip(map(type, lst), lst).index((int, 1))
2
在这里,我们映射每个元素的类型,并通过使用元素压缩类型来创建新列表,并请求(type, value)
的索引。
这是一个使用相同技术的通用迭代解决方案:
>>> from itertools import imap, izip
>>> def index(xs, x):
... it = (i for i, (t, e) in enumerate(izip(imap(type, xs), xs)) if (t, e) == x)
... try:
... return next(it)
... except StopIteration:
... raise ValueError(x)
...
>>> index(lst, (int, 1))
2
这里我们基本上做了相同的事情但迭代地这样做,以免在内存/空间效率方面花费太多。我们是上面相同表达式的迭代器,但是使用imap
和izip
来构建一个自定义索引函数,它返回迭代器中的下一个值,如果没有,则引发ValueError
匹配。
答案 3 :(得分:0)
尝试这个。
for i, j in enumerate([True, False, 1, 3]):
if not isinstance(j, bool) and j == 1:
print i
输出:
2