Functional Python Programming

(Wang) #1
Chapter 11

Or, we could include the conversion function as an argument to the decorator for a
cleansing function as follows:


@then_convert(converter)


def clean(text):


something


In this case, we can choose the @then_convert(converter) style decorator because
we're relying—for the most part—on the built-in conversions. Our point is to show
that the choice is not crystal clear.


The decorator looks as follows:


def then_convert(convert_function):


def clean_convert_decorator(clean_function):


@wraps(clean_function)


def cc_wrapper(text, *args, **kw):


try:


return convert_function(text, *args, **kw)


except (ValueError, decimal.InvalidOperation):


cleaned= clean_function(text)


return convert_function(cleaned, *args, **kw)


return cc_wrapper


return clean_convert_decorator


We've defined a three-layer decorator. At the heart is the cc_wrapper() function that
applies the convert_function function. If this fails, then it uses a clean_function
function and then tries the convert_function function again. This function is
wrapped around the clean_function function by the then_convert_decorator()
concrete decorator function. The concrete decorator has the convert_function
function as a free variable. The concrete decorator is created by the decorator
interface, then_convert(), which is customized by a conversion function.


We can now build a slightly more flexible cleanse and convert function as follows:


@then_convert(int)


def drop_punct(text):


return text.replace(",", "").replace("$", "")


The integer conversion is a decorator applied to the given cleansing function. In this
case, the cleansing function removes $ and , characters. The integer conversion is
wrapped around this cleansing.

Free download pdf