<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=us-ascii">
<meta name=Generator content="Microsoft Word 12 (filtered medium)">
<style>
<!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri","sans-serif";}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
span.EmailStyle17
        {mso-style-type:personal-compose;
        font-family:"Calibri","sans-serif";
        color:windowtext;}
.MsoChpDefault
        {mso-style-type:export-only;}
@page Section1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.Section1
        {page:Section1;}
-->
</style>
<!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang=EN-US link=blue vlink=purple>
<div class=Section1>
<p class=MsoNormal>I’d like to express additional interest in python
patch 1660179, discussed here:<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal><a
href="http://mail.python.org/pipermail/patches/2007-February/021687.html">http://mail.python.org/pipermail/patches/2007-February/021687.html</a><o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal>On several occasions, I’ve had the desire for
something like this. I’ve made due with lambda functions, but as was
mentioned, the lambda is clumsy and harder to read than functools.compose would
be.<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal>A potentially common use-case is when a library has a
multi-decorator use case in which they want to compose a meta decorator out of
one or more individual decorators.<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal>Consider the hypothetical library.<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal># we have three decorators we use commonly<o:p></o:p></p>
<p class=MsoNormal>def dec_register_function_for_x(func):<o:p></o:p></p>
<p class=MsoNormal> # do something with func<o:p></o:p></p>
<p class=MsoNormal> return func<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal>def dec_alter_docstring(func):<o:p></o:p></p>
<p class=MsoNormal> # do something to func.__doc__<o:p></o:p></p>
<p class=MsoNormal> return func<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal>def inject_some_data(data):<o:p></o:p></p>
<p class=MsoNormal> def dec_inject_data(func):<o:p></o:p></p>
<p class=MsoNormal> func.data = data # this may
not be legal, but assume it does something useful<o:p></o:p></p>
<p class=MsoNormal> return func<o:p></o:p></p>
<p class=MsoNormal> return dec_inject_data<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal># we could use these decorators explicitly throughout our
project<o:p></o:p></p>
<p class=MsoNormal>@dec_register_function_for_x<o:p></o:p></p>
<p class=MsoNormal>@dec_alter_docstring<o:p></o:p></p>
<p class=MsoNormal>@dec_inject_some_data(‘foo data 1’)<o:p></o:p></p>
<p class=MsoNormal>def our_func_1(params):<o:p></o:p></p>
<p class=MsoNormal> pass<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal>@dec_register_function_for_x<o:p></o:p></p>
<p class=MsoNormal>@dec_alter_docstring<o:p></o:p></p>
<p class=MsoNormal>@dec_inject_some_data(‘foo data 2’)<o:p></o:p></p>
<p class=MsoNormal>def our_func_2(params):<o:p></o:p></p>
<p class=MsoNormal> pass<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal>For two functions, that’s not too onerous, but if it’s
used throughout the application, it would be nice to abstract the collection of
decorators. One could do this with lambdas.<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal>def meta_decorator(data):<o:p></o:p></p>
<p class=MsoNormal> return lambda func: dec_register_function_for_x(dec_alter_docstring(dec_inject_some_data(data)(func)))<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal>But to me, a compose function is much easier to read and much
more consistent with the decorator usage syntax itself.<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal>def meta_decorator(data):<o:p></o:p></p>
<p class=MsoNormal style='text-indent:.5in'>return compose(dec_register_function_for_x,
dec_alter_docstring, dec_inject_some_data(data))<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal>The latter implementation seems much more readable and
elegant. One doesn’t even need to know the decorator signature to
effectively compose meta_decorators.<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal>I’ve heard it said that Python is not a functional
language, but if that were really the case, then functools would not exist. In
addition to the example described above, I’ve had multiple occasions where
having a general purpose function composition function would have simplified the
implementation by providing a basic functional construct. While Python isn’t
primarily a functional language, it does have some functional constructs, and
this is one of the features that makes Python so versatile; one can program
functionally, procedurally, or in an object-oriented way, all within the same
language.<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal>I admit, I may be a bit biased; my first formal programming
course was taught in Scheme.<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal>Nevertheless, I believe functools is the ideal location for
a very basic and general capability such as composition.<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal>I realize this patch was rejected, but I’d like to
propose reviving the patch and incorporating it into functools.<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal>Regards,<o:p></o:p></p>
<p class=MsoNormal>Jason<o:p></o:p></p>
</div>
</body>
</html>