_.isFunction
The callback spotter that gets a proper BOOLEAN output
- py_dict
- BOOLEAN
_.isFunction checks whether the object on its input is a Python function object - and in the sfinktah/comfy-ovum pack's ovum/underscore family, it's a small piece of luck: it's one of the few nodes the auto-generator gave a properly typed BOOLEAN output instead of the family's usual generic *. That makes it slightly friendlier to wire into boolean logic than most of its siblings.
The family wraps underscore3, a Python port of Underscore.js, and the README's blanket warning applies - work in progress, "not recommended for use in workflows." Which raises the obvious question for a graph environment: when would a Python function object ever be sitting on a wire in the first place?
What it does
The check is type(self.obj) is FunctionType. Two things worth knowing about that:
First, in CPython, FunctionType and LambdaType are the same type object - the standard library defines one as an alias of the other. So this node returns True for any function, whether it was created with def or lambda. The family's separate _.isLambda node will also return True for every function _.isFunction accepts, because they're checking the same type. The distinction between the two nodes is fiction at the type level.
Second, it's not the same as callable(). Classes, instances with __call__, and built-in functions (which are BuiltinFunctionType, a different type) are not plain FunctionType. So a callable object reads as False here.
When would you actually get a function on a wire? Some custom node packs - including this one - accept function objects as inputs. The underscore family itself has iteratee inputs (the map, filter, every nodes) that can take a function built by _.chain-style plumbing, and there's an "underscore function" export node in this pack that outputs the _ factory itself. If you're ever plumbing actual callables through a graph, this is the node that confirms what you're holding.
Inputs and outputs
py_dict- the only input, type*, optional. Namedpy_dictbecause the auto-generator classified the underscoreisFunctionmethod as an "object" method; the tooltip says any JSON-serializable value works, though a function isn't JSON-serializable - wire one in rather than typing one.- Output - a single
BOOLEAN. One of the few family members with a real boolean socket.
Where it fits
Honestly? Rarely. This one exists because the whole underscore method surface was wrapped wholesale, and it shows. If you're debugging a workflow that passes function objects around (iteratee-style nodes), _.isFunction can tell you whether the thing on the wire is a real function or a string/path shorthand that needs resolving. For anyone not plumbing callables, it's a curiosity with a nice socket.
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 - underscore3 ships inside the repo.
Gotchas
- Functions and lambdas are the same type in CPython, so
_.isLambdaagrees with this node on everything. callable(obj)is broader: classes and__call__instances are callable but notFunctionType.- Input is named
py_dictbut it's really "the object" - don't let the label confuse you.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| py_dictopt | * | Primary input object (expected object). You can still pass any JSON-serializable value. Also accepts _.CHAIN to continue chaining. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| BOOLEAN | BOOLEAN | — |