/docs/examples.ipynb
https://github.com/coady/multimethod · Jupyter · 241 lines · 241 code · 0 blank · 0 comment · 0 complexity · 4859e38a2849224bd3172804cdf8f413 MD5 · raw file
- {
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Examples\n",
- "## mutlimethod\n",
- "Multimethods are a mapping of signatures (tuple of types) to functions. They maintain an efficient dispatch tree, and cache the called signatures."
- ]
- },
- {
- "cell_type": "code",
- "metadata": {},
- "outputs": [],
- "source": [
- "from multimethod import multimethod\n",
- "import operator\n",
- "\n",
- "classic_div = multimethod(operator.truediv)\n",
- "classic_div[int, int] = operator.floordiv\n",
- "classic_div"
- ],
- "execution_count": null
- },
- {
- "cell_type": "code",
- "metadata": {},
- "outputs": [],
- "source": [
- "classic_div(3, 2)"
- ],
- "execution_count": null
- },
- {
- "cell_type": "code",
- "metadata": {},
- "outputs": [],
- "source": [
- "classic_div(3.0, 2)"
- ],
- "execution_count": null
- },
- {
- "cell_type": "code",
- "metadata": {},
- "outputs": [],
- "source": [
- "classic_div"
- ],
- "execution_count": null
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Multimethods introspect type annotations and use the name to find existing multimethods."
- ]
- },
- {
- "cell_type": "code",
- "metadata": {},
- "outputs": [],
- "source": [
- "import itertools\n",
- "from typing import Iterable, Sequence\n",
- "\n",
- "\n",
- "@multimethod\n",
- "def chunks(values: Iterable, size):\n",
- " it = iter(values)\n",
- " return iter(lambda: list(itertools.islice(it, size)), [])\n",
- "\n",
- "\n",
- "@multimethod\n",
- "def chunks(values: Sequence, size):\n",
- " for index in range(0, len(values), size):\n",
- " yield values[index : index + size]\n",
- "\n",
- "\n",
- "list(chunks(iter('abcde'), 3))"
- ],
- "execution_count": null
- },
- {
- "cell_type": "code",
- "metadata": {},
- "outputs": [],
- "source": [
- "list(chunks('abcde', 3))"
- ],
- "execution_count": null
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Multimethods also have an explicit `register` method similar to `functools.singledispatch`."
- ]
- },
- {
- "cell_type": "code",
- "metadata": {},
- "outputs": [],
- "source": [
- "@multimethod\n",
- "def window(values, size=2):\n",
- " its = itertools.tee(values, size)\n",
- " return zip(*(itertools.islice(it, index, None) for index, it in enumerate(its)))\n",
- "\n",
- "\n",
- "@window.register\n",
- "def _(values: Sequence, size=2):\n",
- " for index in range(len(values) - size + 1):\n",
- " yield values[index : index + size]\n",
- "\n",
- "\n",
- "list(window(iter('abcde')))"
- ],
- "execution_count": null
- },
- {
- "cell_type": "code",
- "metadata": {},
- "outputs": [],
- "source": [
- "list(window('abcde'))"
- ],
- "execution_count": null
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## overload\n",
- "Whereas multimethods require an `issubclass` relationship, overloads dispatch on any predicates."
- ]
- },
- {
- "cell_type": "code",
- "metadata": {},
- "outputs": [],
- "source": [
- "import asyncio\n",
- "import time\n",
- "from concurrent import futures\n",
- "from multimethod import overload\n",
- "\n",
- "\n",
- "@overload\n",
- "def wait(timeout, func, *args):\n",
- " return futures.ThreadPoolExecutor().submit(func, *args).result(timeout)\n",
- "\n",
- "\n",
- "@overload\n",
- "async def wait(timeout, func: asyncio.iscoroutinefunction, *args):\n",
- " return await asyncio.wait_for(func(*args), timeout)\n",
- "\n",
- "\n",
- "wait(0.5, time.sleep, 0.01)"
- ],
- "execution_count": null
- },
- {
- "cell_type": "code",
- "metadata": {},
- "outputs": [],
- "source": [
- "wait(0.5, asyncio.sleep, 0.01)"
- ],
- "execution_count": null
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## typing subscripts\n",
- "Support for type hints with subscripts."
- ]
- },
- {
- "cell_type": "code",
- "metadata": {},
- "outputs": [],
- "source": [
- "import bisect\n",
- "import random\n",
- "\n",
- "\n",
- "@multimethod\n",
- "def samples(weights: dict):\n",
- " \"\"\"Generate weighted random samples using bisection.\"\"\"\n",
- " keys = list(weights)\n",
- " totals = list(itertools.accumulate(weights.values()))\n",
- " values = [total / totals[-1] for total in totals]\n",
- " while True:\n",
- " yield keys[bisect.bisect_right(values, random.random())]\n",
- "\n",
- "\n",
- "@multimethod\n",
- "def samples(weights: dict[object, int]):\n",
- " \"\"\"Generate weighted random samples more efficiently.\"\"\"\n",
- " keys = list(itertools.chain.from_iterable([key] * weights[key] for key in weights))\n",
- " while True:\n",
- " yield random.choice(keys)\n",
- "\n",
- "\n",
- "weights = {'a': 1, 'b': 2, 'c': 3}\n",
- "next(samples(weights))"
- ],
- "execution_count": null
- },
- {
- "cell_type": "code",
- "metadata": {},
- "outputs": [],
- "source": [
- "weights = {'a': 1.0, 'b': 2.0, 'c': 3.0}\n",
- "next(samples(weights))"
- ],
- "execution_count": null
- }
- ],
- "metadata": {
- "celltoolbar": "Edit Metadata",
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.7.6-final"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
- }