当我们已知一个Python列表始终只包含一个元素时,有没有一种方法可以访问它而不是:
mylist[0]
您可能会问:为什么要这样做?
只是出于好奇。在Python中似乎有一种替代的方法来完成所有事情。
当我们已知一个Python列表始终只包含一个元素时,有没有一种方法可以访问它而不是:
mylist[0]
您可能会问:为什么要这样做?
只是出于好奇。在Python中似乎有一种替代的方法来完成所有事情。
singleitem, = mylist
# Identical in behavior (byte code produced is the same),
# but arguably more readable since a lone trailing comma could be missed:
[singleitem] = mylist
lambda
函数:# The only even semi-reasonable way to retrieve a single item and raise an exception on
# failure for too many, not just too few, elements as an expression, rather than a
# statement, without resorting to defining/importing functions elsewhere to do the work
singleitem = (lambda x: x)(*mylist)
singleitem = next(iter(mylist))
singleitem = mylist.pop()
singleitem = mylist[-1]
for
(因为循环变量在循环终止时保留其最后一个值)进行设置:for singleitem in mylist: break
还有许多其他的方法(结合或变化上述方法的位,或者以隐式迭代方式实现),但您已经掌握了要点。
[singleitem] = mylist
。 - Carsten S[]
进行序列解包(例如for [i, x] in enumerate(iterable):
会让我发疯),但是在解包单个值的情况下,尾随逗号很容易被忽略,出于可读性的原因使用方括号是可以接受的。我已经将其添加到答案中。谢谢! - ShadowRanger(lambda x: x)(*mylist)
;lambda
是函数定义作为表达式,所以你可以定义一个函数,然后将你的可拆包迭代对象传递给其中一个单行函数,它要么因为拆包不精确而死亡(如果拆包不匹配参数计数),要么成功调用函数并返回参数。 - ShadowRangerLOAD_*
将原始可迭代对象加载到堆栈中,一个UNPACK_SEQUENCE 1
来断言它只有一个元素并用该单个元素替换堆栈上的项,以及一个STORE_*
将其放入x
中)。当然,编译后的操作码不是规范,但由于最终结果支持规范中的规则,因此确保不会改变程序行为。 - ShadowRanger我要补充说,more_itertools
库中有一个工具,可以从可迭代对象中返回一个项目。
from more_itertools import one
iterable = ["foo"]
one(iterable)
# "foo"
此外,more_itertools.one
会在可迭代对象为空或多于一个项时引发错误。
iterable = []
one(iterable)
# ValueError: not enough values to unpack (expected 1, got 0)
iterable = ["foo", "bar"]
one(iterable)
# ValueError: too many values to unpack (expected 1)
more_itertools
是一个第三方包 > pip install more-itertools
more_itertools.one
与我的主要解决方案完全等效(一个两行代码的解决方案,element, = iterable
,然后 return element
)。现在它变得更加复杂了(允许自定义异常,对于太短或太长的情况,因此无法从拆包中获得高效的工作,Python会为您引发异常)。这有点可惜;很少有区别是重要的,但代码变得更慢以适应它。 - ShadowRanger(这是对与集合相关的类似问题的我的回答进行调整后的重新发布。)
一种方法是使用reduce
和lambda x: x
。
from functools import reduce
> reduce(lambda x: x, [3]})
3
> reduce(lambda x: x, [1, 2, 3])
TypeError: <lambda>() takes 1 positional argument but 2 were given
> reduce(lambda x: x, [])
TypeError: reduce() of empty sequence with no initial value
优点:
缺点:可能存在“API误用”(请参阅注释)。
lambda
独特的任何好处,你可以传递 任何 接受除两个参数以外的 任何 数量的函数(例如 ord
、lambda: None
等),并获得相同的结果。它“工作”的原因是当输入中只有一个元素时,函数甚至不会被调用,如果被调用,它会立即死亡。你可以简化它,让函数调用语法完成工作,就像我疯狂的版本((lambda x: x)(*mylist)
)一样,具有相同的好处。 - ShadowRangeriter
的调用,因为语言隐式地为你执行了它(就像拆包、使用 for
循环等一样)。 - ShadowRanger
mylist[0]
在至少有一个元素时会成功,但是如果你实际上有30个元素,它不会报错。singleitem, = mylist
可以验证你确切地只有一个元素,不多也不少。 - ShadowRanger