如何安全地解压缩任意单值数据结构(列表,元组,集合等)?

问题描述 投票:1回答:1

有时,我要确保序列或类似集合的数据结构(例如,列表,元组或集合或任何兼容的用户定义数据结构类型)仅包含一个元素,然后使用该元素,但代码会上升如果元素少于或多于一个,则为错误。

幼稚的方法是

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

这对于列表,元组,集合,frozenset甚至对于非容器可迭代变量(例如rangeitertools.takewhile)都适用。 (甚至对于像itertools.count这样的非限定值,因为它正确地报告了“太多的值无法解包”。)

尽管我担心最后一种方法对于代码的读者来说很难理解。 是否有不需要外部第三方依赖的更好的方法?甚至标准库都可以提供?

python containers sequence iterable
1个回答
0
投票

也许尝试next(iter(elements))

© www.soinside.com 2019 - 2024. All rights reserved.