gf lets you write generic functions generic functions with multi-methods, that dispatch on all their arguments.
>>> from gf import generic, method >>> add = generic() >>> type(add) <class 'function'>
Lets define add for two integers:
>>> @method() ... def add(n0: int, n1: int): ... return n0 + n1
Lets test it:
>>> add(1, 2) 3
Calling add with instances of other types fails:
>>> add("Hello ", "World") Traceback (most recent call last): ... NotImplementedError: Generic '__main__.add' has no implementation for type(s): __builtin__.str, __builtin__.str
Of course add can also by defined for two strings:
>>> @method() ... def add(s0: str, s1: str): ... return s0 + s1
Now our hello world example works:
>>> add("Hello ", "World") 'Hello World'
add can also be defined for a string and an integer:
>>> @method() ... def add(s: str, n: int): ... return s + str(n)
Thus we can add a string and a number:
>>> add("You ", 2) 'You 2'
Python’s Special Methods¶
gf.Object implements (nearly) all of the special instance
methods of a python object as a generic function.
The package includes a rational number implementation that makes
heavy use of this feature:
@method() def __add__(a: object, b: Rational): """Add an object and a rational number. `a` is converted to a :class:`Rational` and then both are added.""" return Rational(a) + b @method(Rational, object) def __add__(a: Rational, b: object): """Add a rational number and an object. `b` is converted to a :class:`Rational` and then both are added.""" return a + Rational(b)
gf.Object also has a more Smalltalk means of overwriting
object.__repr__() using a file like object.
Again the rational example is instructive about its usage.
@method() def __out__(rational: Rational, writer: Writer): """Write a nice representation of the rational. Denominators that equal 1 are not printed.""" writer("%d", rational.numerator) if rational.denominator != 1: writer(" / %d", rational.denominator) @method() def __spy__(rational: Rational, writer: Writer): """Write a debug representation of the rational.""" writer("%s(", rational.__class__.__name__) if rational.numerator != 0: writer("%r", rational.numerator) if rational.denominator != 1: writer(", %r", rational.denominator) writer(")")
As usual gf3 can be installed with pip, like this:
pip install gf3
The whole documentation is available at in the following formats
A short sketch of the changes done in each release.
The following was changed in Release 0.2.4:
push()-method accepts an identation string for identing writers.
pop()now accept arbitrary arguments in the general case.
Successfully tested the whole framework with Python 3.5.
The following was changed in Release 0.2.3:
Fixed the long description.
Wrote some documentation about changing the implementation class of a generic function.
The following was changed in Release 0.2.2:
Write more documentation. Especially documented the merge and the isgeneric functions.
Consistency between the long text and on PyPi and the documentation.
Needed to bump the version information, because the homepage in the package-information was wrong 1 and a new upload was needed.
The following was changed in Release 0.2.0:
Ported the whole module to Python 3.6 and Python 3.7.
Exclusively uses parameter annotations to specify the types to dispatch on.
Added standard conforming default implementations for methods like
__add__(). All these methods now raise a proper TypeError instead of raising a NotImplementedError.
Added some means to write generic functions that dispatch types only. This is the generic function equivalent of a class-method.
Added some means to dispatch on single objects. This is the equivalent adding methods to class-instances 2.
The package name for PyPi is now
The following was fixed in Release 0.1.4:
Fixed an issue with variadic methods. Sometimes definitions of variadic methods added after the method was already called where not added.
Specified and implemented a precedence rule for overlapping variadic methods of generic functions.
Improved generated documentation for variadic methods.
Fixed the markup of some notes in the documentation.
The following was changed in Release 0.1.3:
Added variadic methods, e.g. multi-methods with a variable number of arguments.
Improved the long description text a bit and fixed bug in its markup.
Fixed invalid references in the long description.
The following was changed in Release 0.1.2: