.. 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``
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``
Metadata
Release files for polymorphism 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| polymorphism-0.1.2.tar.gz | 5.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| polymorphism-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 15.5 kB
Release files / polymorphism-0.1.2.tar.gz
| Download URL | polymorphism-0.1.2.tar.gz |
|---|---|
| Size | 5.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
946d929f3033b060bb02de00590c95d57ac9e61d004488aab55016591e333851
|
|
BLAKE2b-256 checksum How to use checksums |
545810a0f905196472f03fbf05d9bed76304bc874b38843319cdef37cc4572ec
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/0.12.10 CPython/3.7.2 Linux/4.15.0-43-generic
|
Release files / polymorphism-0.1.2-py3-none-any.whl
| Download URL | polymorphism-0.1.2-py3-none-any.whl |
|---|---|
| Size | 10.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
80609930a34f51839f5ef7c7473a88028e5d0e74876f3bebb7a3dc9afebf6f4c
|
|
BLAKE2b-256 checksum How to use checksums |
8fef71d0ae9232e03fb79962ebace230c677f33bf301311d655c13752a2f9044
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/0.12.10 CPython/3.7.2 Linux/4.15.0-43-generic
|