Simple generic functions
The `simplegeneric` module enables the creation of simple single-dispatch generic functions in Python, akin to built-in functions like `len()` or `iter()`. It achieves this through internal lookup tables rather than special method names. The library, currently at version 0.8.1, was last updated in 2012, signifying a mature but no longer actively developed project that remains functional for its intended purpose. It boasts no external runtime dependencies beyond a minimum Python version.
Warnings
- breaking Prior to version 0.8.1, the `setup.py` script was not fully compatible with Python 3, potentially causing issues during installation or packaging on Python 3 environments. The core module was Python 3 compatible from version 0.8.
- gotcha Dispatching always occurs on the first argument, and this argument must be passed positionally when calling the generic function. Keyword arguments for the first parameter will not trigger dispatch.
- gotcha Standard documentation tools (like `help()`) will only display the signature of the default function. The specialized method signatures are not visible, requiring their documentation to be explicitly stated in the default function's docstring.
- gotcha If a generic function has optional arguments, these arguments (including their defaults) must be explicitly duplicated on every specialized method. Omitting them will result in a `TypeError` if they are not provided in a call.
- gotcha For new projects on Python 3.4+, consider using the built-in `functools.singledispatch` decorator. It provides similar single-dispatch functionality and is actively maintained as part of Python's standard library, offering better integration and type hinting support.
Install
-
pip install simplegeneric
Imports
- generic
from simplegeneric import generic
Quickstart
from simplegeneric import generic
@generic
def move(item, target):
"""Default implementation"""
return f"Default move: {item} to {target}"
@move.when_type(int)
def move_int(item, target):
return f"Moving integer {item} to AD {target}"
@move.when_type(str)
def move_str(item, target):
return f"Moving string '{item}' to {target}. All your {target} are belong to us."
class Zig: pass
zig_instance = Zig()
@move.when_object(zig_instance)
def move_zig(item, target):
return f"Special move for Zig object: {item} to {target}. For great justice!"
assert move(2101, "war") == "Moving integer 2101 to AD war"
assert move("gentlemen", "base") == "Moving string 'gentlemen' to base. All your base are belong to us."
assert move(zig_instance, "doing") == "Special move for Zig object: <object of type Zig> to doing. For great justice!"
assert move(27.0, 56.2) == "Default move: 27.0 to 56.2"