Modul functools

# https://docs.python.org/3/library/functools.html

from functools import partial, wraps, reduce, singledispatch
from decimal import Decimal

print('partial')

basetwo = partial(int, base = 2)
basetwo.__doc__ = 'Convert base 2 string to an int.'
print(basetwo('10010'))
# 18

print(int('10010', 2))
print(int('10010', base = 2))

print('---')
print('reduce')

print('Summe der ganzen Zahlen von 1 bis 10')
def add(x, y): return x + y
print(reduce(add, range(1, 11)))
print(reduce(lambda x, y: x + y, range(1, 11)))

print('---')
print('wraps')

# Dekoratorfunktion; die Dekoration wird über eine Closure realisiert
def add_log(f):
    # ohne den Dekorator @wraps() hätte app_elem.__name__ den Wert 'wrapper' und
    # der Doc-String app_elem.__doc__ ginge verloren
    @wraps(f)
    def wrapper(l, e):
        'der Wrapper, der um f gelegt wird'
        print('füge %s an %s an' % (e, l))
        f(l, e)
    return wrapper

# Nutzung des Dekorators;
# @add_log entspricht app_elem = add_log(app_elem)
@add_log
def app_elem(liste, elem):
    'ein Element an eine Liste anhängen'
    liste.append(elem)

print(app_elem.__name__, '==>', app_elem.__doc__)

print()
l = []
app_elem(l, 55)
app_elem(l, 66)
print(l)

print('---')
print('singledispatch')

# die zu überladende generische Funktion
@singledispatch
def fun(arg, verbose = False):
    if verbose:
        print('Let me just say,', end  = ' ')
        print(arg)

# für den Typ int überladen
@fun.register(int)
def _(arg, verbose = False):
    if verbose:
        print('Strength in numbers, eh?', end = ' ')
        print(arg)

# für den Typ list überladen
@fun.register(list)
def _(arg, verbose = False):
    if verbose:
        print('Enumerate this:')
        for i, elem in enumerate(arg):
            print(i, elem)

# existierde Funktionen inkl. Lambdas kann man durch die funktionale Form
# regsiter() statt des Dekorators registrieren
def nothing(arg, verbose = False):
    print('Nothing.')
fun.register(type(None), nothing)

# für float und Dekorators dieselbe Funktion registrieren
@fun.register(float)
@fun.register(Decimal)
def fun_num(arg, verbose = False):
    if verbose:
        print('Half of your number:', end = ' ')
    print(arg / 2)

fun('Hello, world.')
# Hello, world.

fun('test.', verbose = True)
# Let me just say, test.

fun(42, verbose = True)
# Strength in numbers, eh? 42

fun(['spam', 'spam', 'eggs', 'spam'], verbose = True)
# Enumerate this:
# 0 spam
# 1 spam
# 2 eggs
# 3 spam

fun(None)
# Nothing.

fun(1.23)
# 0.615