Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test for sequences that are not string-like using Python 3's standard library

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 Sequences, 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.

  • Is there any abc in Python's standard library such that islistlike = lambda x: isinstance(x, abc) will behave like the last example above?
  • Is there any design discussion around Sequence vs string-like containers somewhere? (I haven't found anything related to this in the standard library documentation or PEP 3119.)
like image 338
DGrady Avatar asked Apr 19 '17 22:04

DGrady


1 Answers

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.

like image 125
Ethan Furman Avatar answered Nov 15 '22 00:11

Ethan Furman