Skip to main content

Simple generic functions (similar to Python's own len(), pickle.dump(), etc.)

Project description

The simplegeneric module lets you define simple single-dispatch generic functions, akin to Python’s built-in generic functions like len(), iter() and so on. However, instead of using specially-named methods, these generic functions use simple lookup tables, akin to those used by e.g. pickle.dump() and other generic functions found in the Python standard library.

As you can see from the above examples, generic functions are actually quite common in Python already, but there is no standard way to create simple ones. This library attempts to fill that gap, as generic functions are an excellent alternative to the Visitor pattern, as well as being a great substitute for most common uses of adaptation.

This library tries to be the simplest possible implementation of generic functions, and it therefore eschews the use of multiple or predicate dispatch, as well as avoiding speedup techniques such as C dispatching or code generation. But it has absolutely no dependencies, other than Python 2.4, and the implementation is just a single Python module of less than 100 lines.

Usage

Defining and using a generic function is straightforward:

>>> from simplegeneric import generic
>>> @generic
... def move(item, target):
...     """Default implementation goes here"""
...     print "what you say?!"

>>> @move.when_type(int)
... def move_int(item, target):
...     print "In AD %d, %s was beginning." % (item, target)

>>> @move.when_type(str)
... def move_str(item, target):
...     print "How are you %s!!" % item
...     print "All your %s are belong to us." % (target,)

>>> zig = object()
>>> @move.when_object(zig)
... def move_zig(item, target):
...     print "You know what you %s." % (target,)
...     print "For great justice!"

>>> move(2101, "war")
In AD 2101, war was beginning.

>>> move("gentlemen", "base")
How are you gentlemen!!
All your base are belong to us.

>>> move(zig, "doing")
You know what you doing.
For great justice!

>>> move(27.0, 56.2)
what you say?!

Inheritance and Allowed Types

Defining multiple methods for the same type or object is an error:

>>> @move.when_type(str)
... def this_is_wrong(item, target):
...     pass
Traceback (most recent call last):
...
TypeError: <function move...> already has method for type <type 'str'>

>>> @move.when_object(zig)
... def this_is_wrong(item, target): pass
Traceback (most recent call last):
  ...
TypeError: <function move...> already has method for object <object ...>

And the when_type() decorator only accepts classes or types:

>>> @move.when_type(23)
... def move_23(item, target):
...     print "You have no chance to survive!"
Traceback (most recent call last):
  ...
TypeError: 23 is not a type or class

Methods defined for supertypes are inherited following MRO order:

>>> class MyString(str):
...     """String subclass"""

>>> move(MyString("ladies"), "drinks")
How are you ladies!!
All your drinks are belong to us.

Classic class instances are also supported (although the lookup process is slower than for new-style instances):

>>> class X: pass
>>> class Y(X): pass

>>> @move.when_type(X)
... def move_x(item, target):
...     print "Someone set us up the %s!!!" % (target,)

>>> move(X(), "bomb")
Someone set us up the bomb!!!

>>> move(Y(), "dance")
Someone set us up the dance!!!

Defaults and Docs

You can obtain a function’s default implementation using its default attribute:

>>> @move.when_type(Y)
... def move_y(item, target):
...     print "Someone set us up the %s!!!" % (target,)
...     move.default(item, target)

>>> move(Y(), "dance")
Someone set us up the dance!!!
what you say?!

help() and other documentation tools see generic functions as normal function objects, with the same name, attributes, docstring, and module as the prototype/default function:

>>> help(move)
Help on function move:
...
move(*args, **kw)
    Default implementation goes here
...

Limitations

  • The first argument is always used for dispatching, and it must always be passed positionally when the function is called.

  • Documentation tools don’t see the function’s original argument signature, so you have to describe it in the docstring.

  • If you have optional arguments, you must duplicate them on every method in order for them to work correctly. (On the plus side, it means you can have different defaults or required arguments for each method, although relying on that quirk probably isn’t a good idea.)

These restrictions may be lifted in later releases, if I feel the need. They would require runtime code generation the way I do it in RuleDispatch, however, which is somewhat of a pain. (Alternately I could use the BytecodeAssembler package to do the code generation, as that’s a lot easier to use than string-based code generation, but that would introduce more dependencies, and I’m trying to keep this simple so I can just toss it into Chandler without a big footprint increase.)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

simplegeneric-0.5.zip (13.0 kB view details)

Uploaded Source

Built Distribution

simplegeneric-0.5-py2.4.egg (6.6 kB view details)

Uploaded Source

File details

Details for the file simplegeneric-0.5.zip.

File metadata

  • Download URL: simplegeneric-0.5.zip
  • Upload date:
  • Size: 13.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No

File hashes

Hashes for simplegeneric-0.5.zip
Algorithm Hash digest
SHA256 ce1514944f17706a9700c6e1f2f24db1b4027c27ddd9cdaaacc41dd4378f78cb
MD5 cf186041539b84ac6da8d7b84529a765
BLAKE2b-256 891541e21eaa84f5916af0832e0ae5d43107269d2417bdc5051058117f976abe

See more details on using hashes here.

Provenance

File details

Details for the file simplegeneric-0.5-py2.4.egg.

File metadata

File hashes

Hashes for simplegeneric-0.5-py2.4.egg
Algorithm Hash digest
SHA256 7429d7bd0e172766a6ec26b697f7f3003b5e2dae5cd2f5a74fbcc70d5cc63a6d
MD5 1911d4b62d2f1718c71a28851a379499
BLAKE2b-256 2ecc6eb64b885a85d2675f981c2e2294c14b61791781d1c990bfe3d16345cb28

See more details on using hashes here.

Provenance

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page