Skip to main content

Ad hoc polymorphism for Python classes!

Project description

.. highlight:: python

Ad hoc polymorphism for Python classes!
=====================================================

Installation
------------
::

pip install polymorphism

``polymorphism`` support python 3.4+

Usage
-----
To use the ``polymorphism`` simply inherit from the ``Polymorphism`` class::


from polymorphism import Polymorphism


class Simple(Polymorphism):
def calc(self, x: int, y: int) -> None:
pass

def calc(self, x: float, y: float) -> None:
pass

Or use it as metaclass::

from polymorphism import PolymorphismMeta

class Simple(metaclass=PolymorphismMeta):
...


Sometimes adding another class to the inheritance is undesirable, then you can use the ``overload`` decorator::

from polymorphism import overload


class Simple(Polymorphism):
@overload
def calc(self, x: int, y: int) -> None:
pass

@calc.overload
def calc(self, x: float, y: float) -> None:
pass

The only difference between using a decorator and inheriting it is checking for method shading. With ``overload`` the next example will not raise exception::

from polymorphism import overload


class Simple(Polymorphism):
@overload
def calc(self, x: int, y: int) -> None:
pass

calc = 5

And ``calc`` would be only the attribute.

Why?
----
The idea to implement polymorphism is not new. Many libraries `implement <https://github.com/mrocklin/multipledispatch>`_ this idea. Even the `standard library <http://docs.python.org/3.4/library/functools.html#functools.singledispatch>`_ has an implementation.

But they do not support use with classes or standard type annotation.

The basic idea of the implementation was inspired by the great book `Python Cookbook 3rd Edition <http://shop.oreilly.com/product/0636920027072.do>`_ by David Beazley and Brian K. Jones. But the implementation in the book did not support usage of keyword arguments!

Advantages
----------
* Use standard and custom descriptors
* Use naming (keyword) arguments
* Checks for:

* Arguments for variable length
* Missed argument annotation
* Name of wrapped function of descriptor
* Shading method by attribute or data descriptor (like ``property``)
* Redefining the method with the same types

* Using any name for instance, not only ``self``

For all checks is raised ``TypeError`` exception.

Limitations
-----------

* Simple types for dispatching
* ``overload`` should be top of decorators
* Custom descriptor should save wrapped function under "__wrapped__" name
* Obvious, method argument can't be variable length (\* and \*\*)


Examples
--------
There are no restrictions on the use of the number of decorators, you only need to comply the naming convention.

For example::

class Simple(Polymorphism):
def calc(self, x: int, y: int) -> None:
pass

@classmethod
def calc(cls, x: float, y: float) -> None:
pass

@staticmethod
def calc(x: str, y: str) -> None:
pass

Simple().calc(1.0, y=2.0)

While use ``overload`` decorator place it on top::

class Simple:
@overload
def calc(self, x: int, y: int) -> None:
pass

@calc.overload
@classmethod
def calc_float(cls, x: float, y: float) -> None:
pass

@calc.overload
@staticmethod
def calc_str(x: str, y: str) -> None:
pass

With ``overload`` only first method name matter. Other methods can have any other names.

``polymorphism`` checks the class at the creation time::

class Simple(Polymorphism):
def calc(self, x: int, y: int) -> None:
pass

def calc(self, x: int, y: int, z: int = 3) -> None:
pass

The above example will raise ``TypeError`` exception because ``calc`` method overloaded with ``z`` parameter with default value and it is impossible distinct last method from first.

``polymorphism`` will raise ``TypeError`` exception on any wrong overloading, so you don't need worry about correctness of it.

See more examples in `tests.py <https://github.com/asduj/polymorphism/blob/master/tests.py>`_.

To-do
-----

* Complex and builtin types for dispatching like ``List[int]`` or ``Number``

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

polymorphism-0.1.2.tar.gz (5.3 kB view details)

Uploaded Source

Built Distribution

polymorphism-0.1.2-py3-none-any.whl (10.2 kB view details)

Uploaded Python 3

File details

Details for the file polymorphism-0.1.2.tar.gz.

File metadata

  • Download URL: polymorphism-0.1.2.tar.gz
  • Upload date:
  • Size: 5.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/0.12.10 CPython/3.7.2 Linux/4.15.0-43-generic

File hashes

Hashes for polymorphism-0.1.2.tar.gz
Algorithm Hash digest
SHA256 946d929f3033b060bb02de00590c95d57ac9e61d004488aab55016591e333851
MD5 da63bfcff6b9e6dd558b854f8448f15c
BLAKE2b-256 545810a0f905196472f03fbf05d9bed76304bc874b38843319cdef37cc4572ec

See more details on using hashes here.

File details

Details for the file polymorphism-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: polymorphism-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 10.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/0.12.10 CPython/3.7.2 Linux/4.15.0-43-generic

File hashes

Hashes for polymorphism-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 80609930a34f51839f5ef7c7473a88028e5d0e74876f3bebb7a3dc9afebf6f4c
MD5 36afb9d72ffd1a09e78e8529d19cd083
BLAKE2b-256 8fef71d0ae9232e03fb79962ebace230c677f33bf301311d655c13752a2f9044

See more details on using hashes here.

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