一段时间以来,Python已经有了Abstract Base Classes(最初是在PEP 3119中提出的),特别是对于容器类型,这使得编写跨自定义类型泛化的代码更加容易。例如
from collections.abc import Sequence, Set
if isinstance(x, Sequence):
# Handle lists, tuples, or custom objects that behave like lists
elif isinstance(x, Set):
# Handle anything that behaves like a set
其中一个让我几次绊倒的“陷阱”是str
、bytes
和bytearray
都被认为是Sequence
,此外还有更明显的类似列表的对象:
from collections.abc import ByteString, Sequence
s = 'hello'
b = b'hello'
ba = bytearray(b'hello')
lst = [0, 1, 2]
t = (0, 1, 2)
islistlike = lambda x: isinstance(x, Sequence)
list(map(islistlike, [s, b, ba, lst, t])) # -> [True, True, True, True, True]
这当然有道理:通常这三种类型的行为就像字符(或字节)的列表或元组。然而,这似乎是一个非常常见的用例,这个对象x
是列表式的还是字符串式的?解决方法很简单:
islistlike = lambda x: isinstance(x, Sequence) and not isinstance(x, (str, ByteString))
list(map(islistlike, [s, b, ba, lst, t])) # -> [False, False, False, True, True]
但这似乎是一个足够常见的模式,我怀疑我是否遗漏了标准库中的某些内容。你知道吗
abc
使得islistlike = lambda x: isinstance(x, abc)
的行为类似于上面的最后一个示例?你知道吗Sequence
和字符串式容器的设计讨论?(我在标准库文档或PEP 3119中没有找到任何与此相关的内容。)
不,标准库中没有任何东西可以轻松区分
str
和bytes
样序列与其他序列类型。如果这在您的代码库中很常见,那么您可能需要自己开发。你知道吗相关问题 更多 >
编程相关推荐