The generic function package provides means to define generic functions and multi-methods. Additionally classes are provided that enable the user to implement nearly all of Python’s special methods as multi-methods.
One can define generic functions are generics and multi-methods with Python`s special method support with juts two decorator functions and optionally one decorator method.
Generic functions must be defined with the generic()-function.
Create a generic function with a default implementation provided by default_function.
Parameters: | default_function (callable_object) – The generic’s default implementation. |
---|
The generic’s name and docstring are taken from the default_function.
Specialisations for different call signatures can be added with the method() and <generic>.method() decorators.
Note
callable_object can be a function or a type (a new style class).
For example the generic foo()‘s default implemenations just answers the arguments passed as a tuple:
>>> from gf import generic
>>> @generic
... def foo(*arguments):
... """Answers its arguments."""
... return arguments
foo() can be called just like an ordinary function.
>>> foo(1, 2, 3)
(1, 2, 3)
Create an unnamed generic function with no default function and no implementation.
Defining a generic function in this way has the same effect as defining a generic function with a default function that raised a NotImplementedError.
This form is the simplest way to define a generic:
>>> bar = generic()
If this generic function is called a NotImplementedError is raised:
>>> bar("Hello", U"World")
Traceback (most recent call last):
...
NotImplementedError: Generic None has no implementation for type(s): __builtin__.str, __builtin__.unicode
Note
The name is added later when the first multi-method is added with method().
Create a generic function with a name and no default implementation.
Parameters: | name (basestring) – The generic’s name assessable with the .__name__ attribute. |
---|
If you define bar`in this may the `NotImplementedError() raised will contain the generics name:
>>> bar = generic("bar")
>>> bar("Hello", U"World")
Traceback (most recent call last):
...
NotImplementedError: Generic 'bar' has no implementation for type(s): __builtin__.str, __builtin__.unicode
The docstring however is still None:
>>> print bar.__doc__
None
Create a generic function with a name and a docstring, but no default implementation.
Parameters: |
|
---|
The generic now also has a docstring:
>>> print bar.__doc__
A silly generic function for demonstration purposes
Multi-methods can be added to a generic function with the method()-function or the <generic>.method() method.
Add a multi-method for the types given to the generic decorated.
Parameters: |
|
---|
A multi-method specialising the foo() generic for two integers can be added as such:
>>> from gf import method
>>> @method(int, int)
... def foo(i0, i1):
... return i0 + i1
This makes foo() answer 3 for the following call:
>>> foo(1, 2)
3
Caution
The generic function the multi-method is added to, must be defined in the multi-method’s implementation function’s global name-space.
If this is not the case use the <generic>.method() decorator.
Add a multi-method with a variable number of arguments to the generic decorated.
Parameters: |
|
---|
This does essentially the same as method(), but accepts additional arguments to ones the specified by types. This is done by virtually adding an infinite set of of method defintions with the type object used for the unspecified types.
This decorator can be used to implement functions like this:
@variadic_method(TC)
def varfun1(tc, *arguments):
return (tc,) + tuple(reversed(arguments))
This function can be called like this:
varfun1(to, "a", "b", "c")
and behaves in this case like being defined as:
@method(TC, object, object, object)
def varfun1(tc, *arguments):
return (tc,) + tuple(reversed(arguments))
Overlaps of variadic method definitions are always resolved toward the method with more specified types being selected.
This means, that this this function:
@variadic_method(object)
def foo(*arguments):
return arguments
is always perferred over that function:
@variadic_method()
def foo(*arguments):
return list(reversed(arguments))
when called like:
foo("Sepp")
Directly define a multi-method for the types given to <generic>.
Parameters: |
|
---|
<generic> needs not to be available in the implementation function’s name-space. Additionally implementation_function can have a different name than the generic. The later leads to defining an alias of the generic function.
For example a multi-method also available as bar can be defined as such:
>>> @foo.method(str)
... def foobar(a_string):
... return "<%s>" % a_string
With this definition one can either call foo() with a string as follows:
>>> foo("Hi")
'<Hi>'
Or foobar():
>>> foobar("Hi")
'<Hi>'
Directly define a multi-method with a variable number of arguments for the types given to <generic>.
Parameters: |
|
---|
This decorator is the variadic variant of <generic>.method().
As it is sometimes necessary with ordinary single dispatch methods to call methods defined in a base class, it it is sometimes necessary to reuse other implementations of a generic. For this purpose the generic has super()-method.
Parameters: |
|
---|
Directly retrieve and call the multi-method that implements the generic’s functionally for types.
One can add a (silly) implementation for unicode objects to foo() like this:
>>> @method(unicode)
... def foo(a_string):
... return foo.super(object)(a_string)
With this definition the generic’s default implementation will be called for unicode-objects:
>>> foo(U"Sepp")
(u'Sepp',)
While calling foo() wthit a string still yields the old result:
>>> foo("Sepp")
'<Sepp>'
Caution
It is not checked whether the arguments passed are actually instances of types. This is consistent with Python’s notion of duck typing.
The gf-package also provides an abstract base class called gf.AbstractObject and class called gf.Object.
Both classes map nearly all of Python’s special methods to generic functions.
There is also a Writer-class and some convenience and helper generics like as_string(), spy(), __out__() and __spy__().
The implementation of the aforementioned objects is contained in the gf.go, but the objects are also available for direct import from gf.
The following text is generated from the docstring in gf.go.
abs(a) – Same as abs(a).
Called by the AbstractObject.__abs__() special method.
add(a, b) – Same as a + b.
Called by the AbstractObject.__add__() special method. Also called by AbstractObject.__radd__() with arguments reversed.
and_(a, b) – Same as a & b.
Called by the AbstractObject.__and__() special method. Also called by AbstractObject.__rand__() with arguments reversed.
concat(a, b) – Same as a + b, for a and b sequences.
Called by the AbstractObject.__concat__() special method.
contains(a, b) – Same as b in a (note reversed operands).
Called by the AbstractObject.__contains__() special method.
delitem(a, b) – Same as del a[b].
Called by the AbstractObject.__delitem__() special method.
delslice(a, b, c) – Same as del a[b:c].
Called by the AbstractObject.__delslice__() special method.
div(a, b) – Same as a / b when __future__.division is not in effect.
Called by the AbstractObject.__div__() special method. Also called by AbstractObject.__rdiv__() with arguments reversed.
divmod(x, y) -> (quotient, remainder)
Return the tuple ((x-x%y)/y, x%y). Invariant: div*y + mod == x.
Called by the AbstractObject.__divmod__() special method. Also called by AbstractObject.__rdivmod__() with arguments reversed.
eq(a, b) – Same as a==b.
Called by the AbstractObject.__eq__() special method.
floordiv(a, b) – Same as a // b.
Called by the AbstractObject.__floordiv__() special method. Also called by AbstractObject.__rfloordiv__() with arguments reversed.
ge(a, b) – Same as a>=b.
Called by the AbstractObject.__ge__() special method.
getitem(a, b) – Same as a[b].
Called by the AbstractObject.__getitem__() special method.
getslice(a, b, c) – Same as a[b:c].
Called by the AbstractObject.__getslice__() special method.
gt(a, b) – Same as a>b.
Called by the AbstractObject.__gt__() special method.
a = iadd(a, b) – Same as a += b.
Called by the AbstractObject.__iadd__() special method.
a = iand(a, b) – Same as a &= b.
Called by the AbstractObject.__iand__() special method.
a = iconcat(a, b) – Same as a += b, for a and b sequences.
Called by the AbstractObject.__iconcat__() special method.
a = idiv(a, b) – Same as a /= b when __future__.division is not in effect.
Called by the AbstractObject.__idiv__() special method.
a = ifloordiv(a, b) – Same as a //= b.
Called by the AbstractObject.__ifloordiv__() special method.
a = ilshift(a, b) – Same as a <<= b.
Called by the AbstractObject.__ilshift__() special method.
a = imod(a, b) – Same as a %= b.
Called by the AbstractObject.__imod__() special method.
a = imul(a, b) – Same as a *= b.
Called by the AbstractObject.__imul__() special method.
index(a) – Same as a.__index__()
Called by the AbstractObject.__index__() special method.
inv(a) – Same as ~a.
Called by the AbstractObject.__inv__() special method.
invert(a) – Same as ~a.
Called by the AbstractObject.__invert__() special method.
a = ior(a, b) – Same as a |= b.
Called by the AbstractObject.__ior__() special method.
a = ipow(a, b) – Same as a **= b.
Called by the AbstractObject.__ipow__() special method.
a = irepeat(a, b) – Same as a *= b, where a is a sequence, and b is an integer.
Called by the AbstractObject.__irepeat__() special method.
a = irshift(a, b) – Same as a >>= b.
Called by the AbstractObject.__irshift__() special method.
a = isub(a, b) – Same as a -= b.
Called by the AbstractObject.__isub__() special method.
iter(collection) -> iterator iter(callable, sentinel) -> iterator
Get an iterator from an object. In the first form, the argument must supply its own iterator, or be a sequence. In the second form, the callable is called until it returns the sentinel.
Called by the AbstractObject.__iter__() special method.
a = itruediv(a, b) – Same as a /= b when __future__.division is in effect.
Called by the AbstractObject.__itruediv__() special method.
a = ixor(a, b) – Same as a ^= b.
Called by the AbstractObject.__ixor__() special method.
le(a, b) – Same as a<=b.
Called by the AbstractObject.__le__() special method.
lshift(a, b) – Same as a << b.
Called by the AbstractObject.__lshift__() special method. Also called by AbstractObject.__rlshift__() with arguments reversed.
lt(a, b) – Same as a<b.
Called by the AbstractObject.__lt__() special method.
mod(a, b) – Same as a % b.
Called by the AbstractObject.__mod__() special method. Also called by AbstractObject.__rmod__() with arguments reversed.
mul(a, b) – Same as a * b.
Called by the AbstractObject.__mul__() special method. Also called by AbstractObject.__rmul__() with arguments reversed.
ne(a, b) – Same as a!=b.
Called by the AbstractObject.__ne__() special method.
neg(a) – Same as -a.
Called by the AbstractObject.__neg__() special method.
not_(a) – Same as not a.
Called by the AbstractObject.__not__() special method.
or_(a, b) – Same as a | b.
Called by the AbstractObject.__or__() special method. Also called by AbstractObject.__ror__() with arguments reversed.
pos(a) – Same as +a.
Called by the AbstractObject.__pos__() special method.
pow(a, b) – Same as a ** b.
Called by the AbstractObject.__pow__() special method. Also called by AbstractObject.__rpow__() with arguments reversed.
repeat(a, b) – Return a * b, where a is a sequence, and b is an integer.
Called by the AbstractObject.__repeat__() special method.
rshift(a, b) – Same as a >> b.
Called by the AbstractObject.__rshift__() special method. Also called by AbstractObject.__rrshift__() with arguments reversed.
setitem(a, b, c) – Same as a[b] = c.
Called by the AbstractObject.__setitem__() special method.
setslice(a, b, c, d) – Same as a[b:c] = d.
Called by the AbstractObject.__setslice__() special method.
sub(a, b) – Same as a - b.
Called by the AbstractObject.__sub__() special method. Also called by AbstractObject.__rsub__() with arguments reversed.
truediv(a, b) – Same as a / b when __future__.division is in effect.
Called by the AbstractObject.__truediv__() special method. Also called by AbstractObject.__rtruediv__() with arguments reversed.
xor(a, b) – Same as a ^ b.
Called by the AbstractObject.__xor__() special method. Also called by AbstractObject.__rxor__() with arguments reversed.
Create a print string of an object using a Writer.
Note
The function’s name was taken from Prolog’s spy debugging aid.
Multi methods:
Write a just repr() of self.
Write a just repr() of self by directly calling object.__repr__().
Create a print string of an object using a Writer.
Multi methods:
Write a just str() of self.
Write a just str() of self by directly calling object.__str__().
__init__() initializes instantiates instances of AbstractObject and it’s subclasses.
It has a multi method for Object. This multi-method does not accept any additional parameters and has no effect. There is no method for AbstractObject, therefore this class can not be instantiated.
Multi methods:
__call__() is called when instances of AbstractObject are called.
__del__() is called when instances of FinalizingMixin are about to be destroyed.
Convert an AbstractObject to a float.
Convert an AbstractObject to an int.
A simple wrapper around a file like object.
Writer‘s purpose is to simplify the implementation of the generics __out__() and __spy__().
Writer instances are initialised either with a file_like object or with no arguments. In the later case ab instance of StringIO is used.
Output is done by simply calling the writer with at least one string object. The first argument acts as a %-template for formating the other arguments.
The class is intended to be sub-classed for formatted output.
Write text % arguments on the file-like objects.
If no arguments are passed write a newline.
Initialize the Write with a file like object.
Parameters: | file_like – An optional file-like object. |
---|
list of weak references to the object (if defined)
An abstract (mixin) class that maps all the python magic functions to generics.
Call the __call__() generic function.
concat(a, b) – Same as a + b, for a and b sequences.
Calls the __concat__()-generic with its arguments.
contains(a, b) – Same as b in a (note reversed operands).
Calls the __contains__()-generic with its arguments.
delitem(a, b) – Same as del a[b].
Calls the __delitem__()-generic with its arguments.
delslice(a, b, c) – Same as del a[b:c].
Calls the __delslice__()-generic with its arguments.
div(a, b) – Same as a / b when __future__.division is not in effect.
Calls the __div__()-generic with its arguments.
divmod(x, y) -> (quotient, remainder)
Return the tuple ((x-x%y)/y, x%y). Invariant: div*y + mod == x.
Calls the __divmod__()-generic with its arguments.
Convert the object to a float by calling the __float__() generic.
floordiv(a, b) – Same as a // b.
Calls the __floordiv__()-generic with its arguments.
getitem(a, b) – Same as a[b].
Calls the __getitem__()-generic with its arguments.
getslice(a, b, c) – Same as a[b:c].
Calls the __getslice__()-generic with its arguments.
a = iadd(a, b) – Same as a += b.
Calls the __iadd__()-generic with its arguments.
a = iand(a, b) – Same as a &= b.
Calls the __iand__()-generic with its arguments.
a = iconcat(a, b) – Same as a += b, for a and b sequences.
Calls the __iconcat__()-generic with its arguments.
a = idiv(a, b) – Same as a /= b when __future__.division is not in effect.
Calls the __idiv__()-generic with its arguments.
a = ifloordiv(a, b) – Same as a //= b.
Calls the __ifloordiv__()-generic with its arguments.
a = ilshift(a, b) – Same as a <<= b.
Calls the __ilshift__()-generic with its arguments.
a = imod(a, b) – Same as a %= b.
Calls the __imod__()-generic with its arguments.
a = imul(a, b) – Same as a *= b.
Calls the __imul__()-generic with its arguments.
index(a) – Same as a.__index__()
Calls the __index__()-generic with its arguments.
Call the __init__() generic function.
invert(a) – Same as ~a.
Calls the __invert__()-generic with its arguments.
a = ior(a, b) – Same as a |= b.
Calls the __ior__()-generic with its arguments.
a = ipow(a, b) – Same as a **= b.
Calls the __ipow__()-generic with its arguments.
a = irepeat(a, b) – Same as a *= b, where a is a sequence, and b is an integer.
Calls the __irepeat__()-generic with its arguments.
a = irshift(a, b) – Same as a >>= b.
Calls the __irshift__()-generic with its arguments.
a = isub(a, b) – Same as a -= b.
Calls the __isub__()-generic with its arguments.
iter(collection) -> iterator iter(callable, sentinel) -> iterator
Get an iterator from an object. In the first form, the argument must supply its own iterator, or be a sequence. In the second form, the callable is called until it returns the sentinel.
Calls the __iter__()-generic with its arguments.
a = itruediv(a, b) – Same as a /= b when __future__.division is in effect.
Calls the __itruediv__()-generic with its arguments.
a = ixor(a, b) – Same as a ^= b.
Calls the __ixor__()-generic with its arguments.
lshift(a, b) – Same as a << b.
Calls the __lshift__()-generic with its arguments.
add(a, b) – Same as a + b.
Calls the __add__()-generic with its arguments reversed.
and_(a, b) – Same as a & b.
Calls the __and__()-generic with its arguments reversed.
div(a, b) – Same as a / b when __future__.division is not in effect.
Calls the __div__()-generic with its arguments reversed.
divmod(x, y) -> (quotient, remainder)
Return the tuple ((x-x%y)/y, x%y). Invariant: div*y + mod == x.
Calls the __divmod__()-generic with its arguments reversed.
repeat(a, b) – Return a * b, where a is a sequence, and b is an integer.
Calls the __repeat__()-generic with its arguments.
floordiv(a, b) – Same as a // b.
Calls the __floordiv__()-generic with its arguments reversed.
lshift(a, b) – Same as a << b.
Calls the __lshift__()-generic with its arguments reversed.
mod(a, b) – Same as a % b.
Calls the __mod__()-generic with its arguments reversed.
mul(a, b) – Same as a * b.
Calls the __mul__()-generic with its arguments reversed.
or_(a, b) – Same as a | b.
Calls the __or__()-generic with its arguments reversed.
pow(a, b) – Same as a ** b.
Calls the __pow__()-generic with its arguments reversed.
rshift(a, b) – Same as a >> b.
Calls the __rshift__()-generic with its arguments reversed.
rshift(a, b) – Same as a >> b.
Calls the __rshift__()-generic with its arguments.
sub(a, b) – Same as a - b.
Calls the __sub__()-generic with its arguments reversed.
truediv(a, b) – Same as a / b when __future__.division is in effect.
Calls the __truediv__()-generic with its arguments reversed.
xor(a, b) – Same as a ^ b.
Calls the __xor__()-generic with its arguments reversed.
setitem(a, b, c) – Same as a[b] = c.
Calls the __setitem__()-generic with its arguments.
setslice(a, b, c, d) – Same as a[b:c] = d.
Calls the __setslice__()-generic with its arguments.
Answer the objects print-string by calling as_string().
truediv(a, b) – Same as a / b when __future__.division is in effect.
Calls the __truediv__()-generic with its arguments.
list of weak references to the object (if defined)
A mixin class with __del__ implemented as a generic function.
Note
This functionality was separated into mixin class, because Python’s cycle garbage collector does not collect classes with a __del__() method. Inherit from this class if you really need __del__().
list of weak references to the object (if defined)
Answer an object’s debug string.
This is done by creating a Writer instance and calling the __spy__() generic with the object and the writer. The using Writer.get_text() to retrieve the text written.
Note
The function’s name was taken from Prolog’s spy debugging aid.
Answer an object’s print string.
This is done by creating a Writer instance and calling the __out__() generic with the object and the writer. The using Writer.get_text() to retrieve the text written.