Python 如何安全地解压任意单值数据结构(列表、元组、集合等)?
有时,我希望确保序列或类似集合的数据结构(例如,列表、元组或集合,或任何兼容的用户定义的数据结构类型)正好包含一个元素,然后使用该元素,但如果元素少于或多于该元素,则代码会出错 幼稚的做法是不可取的Python 如何安全地解压任意单值数据结构(列表、元组、集合等)?,python,containers,sequence,iterable,Python,Containers,Sequence,Iterable,有时,我希望确保序列或类似集合的数据结构(例如,列表、元组或集合,或任何兼容的用户定义的数据结构类型)正好包含一个元素,然后使用该元素,但如果元素少于或多于该元素,则代码会出错 幼稚的做法是不可取的 def unpack_single(elements): assert len(elements) == 1, f"expected exactly 1 element, found {len(elements)} elements" return elements[0] 这适用于
def unpack_single(elements):
assert len(elements) == 1, f"expected exactly 1 element, found {len(elements)} elements"
return elements[0]
这适用于列表和元组:
>>> unpack_single([5])
5
>>> unpack_single((42,))
42
>>> unpack_single([]) # fails as expected
AssertionError: expected exactly 1 element, found 0 elements
>>> unpack_single(tuple()) # fails as expected
AssertionError: expected exactly 1 element, found 0 elements
>>> unpack_single([23, "foo"]) # fails as expected
AssertionError: expected exactly 1 element, found 2 elements
>>> unpack_single(tuple("foobar")) # fails as expected
AssertionError: expected exactly 1 element, found 6 elements
但它不适用于不可下标的集合:
>>> unpack_single({"wat"}) # fails, but I want this to work, too!
TypeError: 'set' object is not subscriptable
替代方案
def unpack_single(elements):
assert len(elements) == 1, f"expected exactly 1 element, found {len(elements)} elements"
return elements.pop()
对集合有效,但对元组和冻结集无效,因为它们是不可变的,并且不实现pop()
方法
一种优雅但可能有点晦涩的方法是对长度为1的变量列表使用解包(解构赋值):
def unpack_single(elements):
only_element, = elements
return only_element
这适用于列表、元组、集合、冻结集,甚至适用于非容器iterables,如range
或itertools.takewhile
。(甚至对于像itertools.count
这样的非有限值,因为它正确地报告了这些值的“太多而无法解包”)
尽管我担心最后一种方法对于代码的读者来说很难理解有没有更好的方法不需要外部第三方依赖关系?甚至可能是标准库提供的东西?试试next(iter(elements))
可能
def unpack_single(elements):
assert len(elements) == 1, f"expected exactly 1 element, found {len(elements)} elements"
return next(iter(elements))
是什么让你觉得最后一种方法太难理解?我没有读最后一部分,只是元素,=元素看起来像一个好的例子solution@SebastianGaweda我不知道。我很理解,但我想那可能只是因为我自己想出来的。它是否充分清楚地传达了意图(如果存在意外数量的元素,则会失败)?如果是这样的话,我认为这确实很好。顺便说一句,因为我确实有一个有效的解决方案,只是不知道它有多“好”,堆栈溢出是问这个问题的正确位置还是我应该问的位置?我认为代码复查对于这个问题更合适,因为在这种情况下很难确定“更好”的方法。我发现您的解决方案是您想要完成的任务的最简单的最小实现,并且易于阅读,但并非每个阅读它的人都持有这种观点。如果您能向我展示另一个代码片段并让我相信它是一个改进的实现,我会感到惊讶。