Single Dispatch Generic Functions
Posted April 29, 2021 by clannadzsy ‐ 2 min read
"""
from Fluent Python 2nd Example 9-19
"""
from functools import singledispatch
from collections import abc
import fractions
import decimal
import html
import numbers
@singledispatch
def htmlize(obj: object) -> str:
content = html.escape(repr(obj))
return f'<pre>{content}</pre>'
@htmlize.register
def _(text: str) -> str:
content = html.escape(text).replace('\n', '<br>\n')
return f'<p>{content}</p>'
@htmlize.register
def _(seq: abc.Sequence) -> str:
inner = '</li>\n<li>'.join(htmlize(item) for item in seq)
return '<ul>\n<li>' + inner + '</li>\n</ul>'
@htmlize.register
def _(n: numbers.Integral) -> str:
return f'<pre>{n} (0x{n:x})</pre>'
@htmlize.register
def _(n: bool) -> str:
return f'<pre>{n}</pre>'
@htmlize.register(fractions.Fraction)
def _(x) -> str:
frac = fractions.Fraction(x)
return f'<pre>{frac.numerator}/{frac.denominator}</pre>'
@htmlize.register(decimal.Decimal)
@htmlize.register(float)
def _(x) -> str:
frac = fractions.Fraction(x).limit_denominator()
return f'<pre>{x} ({frac.numerator}/{frac.denominator})</pre>'
if __name__ == '__main__':
param_list = [
{1, 2, 3},
abs,
'Hello \n World',
123,
['linux', 1, {1, 2, 3}],
True,
fractions.Fraction(2, 3),
0.1,
decimal.Decimal('0.123456')
]
for p in param_list:
print(p)
print(htmlize(p))
print('\n')
# {1, 2, 3}
# <pre>{1, 2, 3}</pre>
#
#
# <built-in function abs>
# <pre><built-in function abs></pre>
#
#
# Hello
# World
# <p>Hello <br>
# World</p>
#
#
# 123
# <pre>123 (0x7b)</pre>
#
#
# ['linux', 1, {1, 2, 3}]
# <ul>
# <li><p>linux</p></li>
# <li><pre>1 (0x1)</pre></li>
# <li><pre>{1, 2, 3}</pre></li>
# </ul>
#
#
# True
# <pre>True</pre>
#
#
# 2/3
# <pre>2/3</pre>
#
#
# 0.1
# <pre>0.1 (1/10)</pre>
#
#
# 0.123456
# <pre>0.123456 (1929/15625)</pre>