/docs/examples.ipynb

https://github.com/coady/multimethod · Jupyter · 241 lines · 241 code · 0 blank · 0 comment · 0 complexity · 4859e38a2849224bd3172804cdf8f413 MD5 · raw file

  1. {
  2. "cells": [
  3. {
  4. "cell_type": "markdown",
  5. "metadata": {},
  6. "source": [
  7. "# Examples\n",
  8. "## mutlimethod\n",
  9. "Multimethods are a mapping of signatures (tuple of types) to functions. They maintain an efficient dispatch tree, and cache the called signatures."
  10. ]
  11. },
  12. {
  13. "cell_type": "code",
  14. "metadata": {},
  15. "outputs": [],
  16. "source": [
  17. "from multimethod import multimethod\n",
  18. "import operator\n",
  19. "\n",
  20. "classic_div = multimethod(operator.truediv)\n",
  21. "classic_div[int, int] = operator.floordiv\n",
  22. "classic_div"
  23. ],
  24. "execution_count": null
  25. },
  26. {
  27. "cell_type": "code",
  28. "metadata": {},
  29. "outputs": [],
  30. "source": [
  31. "classic_div(3, 2)"
  32. ],
  33. "execution_count": null
  34. },
  35. {
  36. "cell_type": "code",
  37. "metadata": {},
  38. "outputs": [],
  39. "source": [
  40. "classic_div(3.0, 2)"
  41. ],
  42. "execution_count": null
  43. },
  44. {
  45. "cell_type": "code",
  46. "metadata": {},
  47. "outputs": [],
  48. "source": [
  49. "classic_div"
  50. ],
  51. "execution_count": null
  52. },
  53. {
  54. "cell_type": "markdown",
  55. "metadata": {},
  56. "source": [
  57. "Multimethods introspect type annotations and use the name to find existing multimethods."
  58. ]
  59. },
  60. {
  61. "cell_type": "code",
  62. "metadata": {},
  63. "outputs": [],
  64. "source": [
  65. "import itertools\n",
  66. "from typing import Iterable, Sequence\n",
  67. "\n",
  68. "\n",
  69. "@multimethod\n",
  70. "def chunks(values: Iterable, size):\n",
  71. " it = iter(values)\n",
  72. " return iter(lambda: list(itertools.islice(it, size)), [])\n",
  73. "\n",
  74. "\n",
  75. "@multimethod\n",
  76. "def chunks(values: Sequence, size):\n",
  77. " for index in range(0, len(values), size):\n",
  78. " yield values[index : index + size]\n",
  79. "\n",
  80. "\n",
  81. "list(chunks(iter('abcde'), 3))"
  82. ],
  83. "execution_count": null
  84. },
  85. {
  86. "cell_type": "code",
  87. "metadata": {},
  88. "outputs": [],
  89. "source": [
  90. "list(chunks('abcde', 3))"
  91. ],
  92. "execution_count": null
  93. },
  94. {
  95. "cell_type": "markdown",
  96. "metadata": {},
  97. "source": [
  98. "Multimethods also have an explicit `register` method similar to `functools.singledispatch`."
  99. ]
  100. },
  101. {
  102. "cell_type": "code",
  103. "metadata": {},
  104. "outputs": [],
  105. "source": [
  106. "@multimethod\n",
  107. "def window(values, size=2):\n",
  108. " its = itertools.tee(values, size)\n",
  109. " return zip(*(itertools.islice(it, index, None) for index, it in enumerate(its)))\n",
  110. "\n",
  111. "\n",
  112. "@window.register\n",
  113. "def _(values: Sequence, size=2):\n",
  114. " for index in range(len(values) - size + 1):\n",
  115. " yield values[index : index + size]\n",
  116. "\n",
  117. "\n",
  118. "list(window(iter('abcde')))"
  119. ],
  120. "execution_count": null
  121. },
  122. {
  123. "cell_type": "code",
  124. "metadata": {},
  125. "outputs": [],
  126. "source": [
  127. "list(window('abcde'))"
  128. ],
  129. "execution_count": null
  130. },
  131. {
  132. "cell_type": "markdown",
  133. "metadata": {},
  134. "source": [
  135. "## overload\n",
  136. "Whereas multimethods require an `issubclass` relationship, overloads dispatch on any predicates."
  137. ]
  138. },
  139. {
  140. "cell_type": "code",
  141. "metadata": {},
  142. "outputs": [],
  143. "source": [
  144. "import asyncio\n",
  145. "import time\n",
  146. "from concurrent import futures\n",
  147. "from multimethod import overload\n",
  148. "\n",
  149. "\n",
  150. "@overload\n",
  151. "def wait(timeout, func, *args):\n",
  152. " return futures.ThreadPoolExecutor().submit(func, *args).result(timeout)\n",
  153. "\n",
  154. "\n",
  155. "@overload\n",
  156. "async def wait(timeout, func: asyncio.iscoroutinefunction, *args):\n",
  157. " return await asyncio.wait_for(func(*args), timeout)\n",
  158. "\n",
  159. "\n",
  160. "wait(0.5, time.sleep, 0.01)"
  161. ],
  162. "execution_count": null
  163. },
  164. {
  165. "cell_type": "code",
  166. "metadata": {},
  167. "outputs": [],
  168. "source": [
  169. "wait(0.5, asyncio.sleep, 0.01)"
  170. ],
  171. "execution_count": null
  172. },
  173. {
  174. "cell_type": "markdown",
  175. "metadata": {},
  176. "source": [
  177. "## typing subscripts\n",
  178. "Support for type hints with subscripts."
  179. ]
  180. },
  181. {
  182. "cell_type": "code",
  183. "metadata": {},
  184. "outputs": [],
  185. "source": [
  186. "import bisect\n",
  187. "import random\n",
  188. "\n",
  189. "\n",
  190. "@multimethod\n",
  191. "def samples(weights: dict):\n",
  192. " \"\"\"Generate weighted random samples using bisection.\"\"\"\n",
  193. " keys = list(weights)\n",
  194. " totals = list(itertools.accumulate(weights.values()))\n",
  195. " values = [total / totals[-1] for total in totals]\n",
  196. " while True:\n",
  197. " yield keys[bisect.bisect_right(values, random.random())]\n",
  198. "\n",
  199. "\n",
  200. "@multimethod\n",
  201. "def samples(weights: dict[object, int]):\n",
  202. " \"\"\"Generate weighted random samples more efficiently.\"\"\"\n",
  203. " keys = list(itertools.chain.from_iterable([key] * weights[key] for key in weights))\n",
  204. " while True:\n",
  205. " yield random.choice(keys)\n",
  206. "\n",
  207. "\n",
  208. "weights = {'a': 1, 'b': 2, 'c': 3}\n",
  209. "next(samples(weights))"
  210. ],
  211. "execution_count": null
  212. },
  213. {
  214. "cell_type": "code",
  215. "metadata": {},
  216. "outputs": [],
  217. "source": [
  218. "weights = {'a': 1.0, 'b': 2.0, 'c': 3.0}\n",
  219. "next(samples(weights))"
  220. ],
  221. "execution_count": null
  222. }
  223. ],
  224. "metadata": {
  225. "celltoolbar": "Edit Metadata",
  226. "language_info": {
  227. "codemirror_mode": {
  228. "name": "ipython",
  229. "version": 3
  230. },
  231. "file_extension": ".py",
  232. "mimetype": "text/x-python",
  233. "name": "python",
  234. "nbconvert_exporter": "python",
  235. "pygments_lexer": "ipython3",
  236. "version": "3.7.6-final"
  237. }
  238. },
  239. "nbformat": 4,
  240. "nbformat_minor": 2
  241. }