_.isListlike
The pragmatic 'can I iterate this' test, without exact-type pedantry
- obj
- *
_.isListlike is the sibling of _.isList that stops being pedantic about types. Where _.isList demands the exact Python list type, this one asks a more practical question: does this object act like a list? It's from the sfinktah/comfy-ovum pack's ovum/underscore family - auto-generated wrappers around underscore3, a Python port of Underscore.js - and it's one of the few family members with a duck-typing soul.
The family's README warning is worth repeating once: work in progress, "not recommended for use in workflows." Mostly that's aimed at the exotic method nodes. This one's fine - it's a couple of attribute checks, easy to reason about.
What it does
The underlying implementation is a small static helper, _isListlike, that checks whether the object has three callable attributes: append, remove, and __len__. If all three exist and are callable, it's "listlike."
Work through what that means for real data:
- A
list→True(has append, remove,__len__). - A
set→False(noremovethat matches... actually sets haveremoveand__len__but noappend- soFalse). - A
tuple→False(no append or remove; it's immutable). - A
str→False(no append or remove). - A
dict→False(no append or remove, though it has__len__).
So it's a "can I treat this as a mutable, indexable, sized sequence" test. Note it's not a full sequence check - __getitem__ isn't part of the test, and neither is __iter__. It's tuned to the specific operations the pack's own list-manipulation nodes use, which makes it a natural gate before you feed something into a list-op node.
Like everything in the family, feed it a plain value and get the boolean back, or feed it a _.CHAIN and it runs on the wrapped object, passing the chain onward.
Inputs and outputs
obj- the only input, type*, optional.- Output - a single
*socket holding a Python bool. Same family quirk as most of these: the value is a real boolean, the socket type is generic, so a strictBOOLEANconsumer might want a cast.
Where it fits
Use it where "exactly a list" is the wrong question. If an upstream node could hand you a list or a tuple - which happens constantly with Python-ported node packs - _.isList says False for the tuple and _.isListlike says True. That's the one you actually want when the next step is "iterate it" or "feed it to a list operation." The tuple isn't a problem for the downstream op; the downstream op just needs to know the shape is iterable-and-sized, not exactly list.
Installing it
Install the pack via ComfyUI Manager (search comfy-ovum) or:
cd ComfyUI/custom_nodes
git clone https://github.com/sfinktah/comfy-ovum
Restart ComfyUI. No extra dependencies for this node - underscore3 is bundled in the repo - and Manager handles the pack's requirements.txt for everything else.
Gotchas
- Sets, tuples, strings, and dicts all come back
False. If "iterable" is your only concern, this is more conservative thanisinstance(x, collections.abc.Iterable)would be. - It checks for methods, not for
__getitem__or__iter__, so a custom class that's indexable but lacksappendreads as not-listlike. That's by design, but it can surprise you with exotic object types. - Output wire is
*, notBOOLEAN- value is right, type label is loose.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| objopt | * | Primary input object. Also accepts _.CHAIN to continue chaining. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| * | * | — |