For some time, Python has had Abstract Base Classes (proposed orignally in PEP 3119) that, especially for container types, make it easier to write code that generalizes across custom types. For example,
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
One of the ‘gotchas’ that’s tripped me up a few times is that str
, bytes
, and bytearray
are all considered Sequence
s, in addition to more obviously list-like objects:
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]
This certainly makes sense: usually these three types behave just like lists or tuples of characters (or bytes). However, it seems like a pretty common use case to ask, is this object x
both list-like and not string-like? The fix is straightforward:
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]
But this seems like it would be a common enough pattern that I wonder if I'm missing something in the standard library.
abc
in Python's standard library such that islistlike = lambda x: isinstance(x, abc)
will behave like the last example above?Sequence
vs string-like containers somewhere? (I haven't found anything related to this in the standard library documentation or PEP 3119.)No, there is nothing in the standard library to easily distinguish between str
and bytes
-like sequences vs other sequence types. If this is common in your code-base then you may want to roll your own.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With