如何检测列表、元组或一般非字符串序列的列表?

How can I detect a list of lists, of tuples or of non-string sequences in general?

提问人:jtlz2 提问时间:6/27/2023 最后编辑:jtlz2 更新时间:6/27/2023 访问量:73

问:

我有一个 ,我想对 是否包含任何 of: s 或 s 或非字符串 s 或类似对象进行布尔测试。listlistlisttuplesequencelist

如果 is of s 或任何其他未指定的可迭代对象,我想要测试返回。Falseliststr

如何在 python 中有效(懒惰地)评估这一点?

例如,我是否应该与列表理解条件一起使用?isinstance(x, collections.Sequence)

或者我可以折叠元素并测试残差吗?list

事情是这样的:

{a, , , , , } 是 {s, s, s, ...}bcdefstrintUUID

x1 = [a, b, c, d, e, f]
x2 = [(a, b),(c, d),(e, f)]
x2 = [[a, b],[c, d],[e, f]]

result = dict(x1=False, x2=True, x3=True)

def func(y):
    ...
    return z

for x in [x1, x2, x3]:
    assert func(x) == result[x], "Function needs an answer!"

什么是填充的好方法?func

PS:这是一个相关的类似列表的对象(类型)的示例:OmegaConf.ListConfig

https://github.com/omry/omegaconf/blob/a68b149b8e1a9e9a0cabc83e8691df8c6620909a/omegaconf/listconfig.py#L42C1-L43C1

Python 列表 元组 序列

评论

2赞 deceze 6/27/2023
那么,是否正确匹配您想要的值,而不是匹配您不需要的值......?isinstance(x, collections.Sequence)
2赞 Barmar 6/27/2023
你不需要列表理解。将 or 函数与生成器一起使用,具体取决于要测试的内容。他们都很懒惰,一旦确定了答案,他们就会停下来。any()all()
1赞 user2390182 6/27/2023
你没有提供一些关于你的实际问题的细节,以及你到底想要匹配哪些类型,哪些你不匹配。就像一些示例输入和输出一样。
0赞 jtlz2 6/27/2023
感谢所有有用的反馈 - 我将很快解决这些问题
0赞 user2390182 6/27/2023
当你在做这件事时,什么对你来说构成了一个类似列表的对象?

答:

-1赞 hacker315 6/27/2023 #1
>>> a = ['a', 1, [2,4]]
>>> any(map(lambda x: isinstance(x, str), a))
True
>>> any(map(lambda x: isinstance(x, int), a))
True
>>> any(map(lambda x: isinstance(x, list), a))
True
>>> any(map(lambda x: isinstance(x, float), a))
False
0赞 user2390182 6/27/2023 #2

因此,您希望从类似序列的对象中排除(并且可能):strbytes

from typing import Sequence

# type test single item
def is_seq_but_not_str(item):
    return isinstance(item, Sequence) and not isinstance(item, (str, bytes))

# test list if any item passes test
def func(y):
    return any(map(is_seq_but_not_str, y))

序列协议本身并不是一个 100% 定义明确的协议,但大多数来源都引用了一些 、 、 、 的存在(根据我的主观相关顺序;请注意,后三个可以通过前两个来实现)。例如,仅针对前两个测试将包括明确不是序列的测试。 如果测试非常严格,则应为任何项目()提出一个,为非项目提出一个。相反,映射(如 )只是为任何非成员项引发 a。__len____getitem____reversed____contains____iter__dict__getitem__IndexErrornot 0 <= item < len(seq)TypeErrorintdictKeyError

因此,对于不继承(或注册)的自定义类,此类测试可能如下所示:Sequence

def custom_is_seq_but_not_str(item, 
                              required=("__len__", "__getitem__", "__reversed__")):
    if isinstance(item, (str, bytes)):
        return False
    return all(hasattr(item, attr) for attr in required)
    # or a little stronger
    # return all(callable(getattr(item, attr, None)) for attr in required)