Given a list of functions, it seems there must be a
Pythonic approach to composition. Something like
def compose(fns): return lambda x: reduce(lambda f,g: f(g),fns)(x)
This will not work because the argument 'x' is not "inside".
What is the proper formulation?
Thanks,
Alan Isaac 6 3351
Alan G Isaac wrote: Given a list of functions, it seems there must be a Pythonic approach to composition. Something like
def compose(fns): return lambda x: reduce(lambda f,g: f(g),fns)(x)
This will not work because the argument 'x' is not "inside". What is the proper formulation?
You need to pass a function that makes a function (a "factory") to reduce(): fns = [lambda x: x+2, lambda x: x*2, lambda x: x*x] def compose(f, g):
.... def fog(x):
.... return f(g(x))
.... return fog
.... g1 = reduce(compose, fns) g1(2)
10
The same with lambdas:
g2 = reduce(lambda f, g: lambda x: f(g(x)), fns) g2(2)
10
Peter
Alan G Isaac <ai****@american.edu> wrote: Given a list of functions, it seems there must be a Pythonic approach to composition. Something like
def compose(fns): return lambda x: reduce(lambda f,g: f(g),fns)(x)
This will not work because the argument 'x' is not "inside". What is the proper formulation?
There are probably several ways to do it.
The following is the one which come to my mind first.
The trick is to first define a function that composes
two functions, and then use reduce() to apply it to an
arbitrary number of functions. def compose2 (f, g):
.... def h (x):
.... return f(g(x))
.... return h
.... def compose (fns):
.... return reduce(compose2, fns)
....
Some testing:
def add42 (x): return x + 42
.... def mul2 (x): return x * 2
.... def sub5 (x): return x - 5
.... def div3 (x): return x / 3
.... a = compose((add42, mul2, sub5, div3)) a(1)
27
There's no need to juggle with lambda in this case.
Lambda has its uses, but this isn't one of them.
Best regards
Oliver
--
Oliver Fromme, Konrad-Celtis-Str. 72, 81369 Munich, Germany
``All that we see or seem is just a dream within a dream.''
(E. A. Poe)
"Peter Otten" <__*******@web.de> wrote in message
news:cl************@news.t-online.com... g2 = reduce(lambda f, g: lambda x: f(g(x)), fns)
Cool. That gets me there. I think
def compose(fns) : return reduce(lambda f, g: lambda x: f(g(x)), fns)
does exactly what I want.
Thanks,
Alan Isaac
"Oliver Fromme" <ol**@haluter.fromme.com> wrote in message
news:2u*************@uni-berlin.de... There's no need to juggle with lambda in this case. Lambda has its uses, but this isn't one of them.
I kind of like the lambda version (see Peter's post).
But maybe it is more opaque.
Thanks,
Alan
In article <10*************@corp.supernews.com>,
"Alan G Isaac" <ai****@american.edu> wrote: Given a list of functions, it seems there must be a Pythonic approach to composition. Something like
def compose(fns): return lambda x: reduce(lambda f,g: f(g),fns)(x)
This will not work because the argument 'x' is not "inside". What is the proper formulation?
If you are only concerned with unary functions, then composition is
fairly trivial to deal with:
def compose(*fns):
def id(x): return x
def c2(f, g):
def h(x): return f(g(x))
return h
return reduce(c2, fns, id)
However, if you want to deal with functions that may take multiple
arguments, you must be a little more clever. Here's one way that seems
to work okay:
def compose(*fns):
def id(*args): return args
def box(res):
if isinstance(res, (list, tuple)):
return res
else:
return (res,)
def unbox(res):
if isinstance(res, (list, tuple)) and len(res) == 1:
return res[0]
else:
return res
def c2(f, g):
def h(*args):
return unbox(f(*box(g(*args))))
return h
return reduce(c2, fns, id)
For instance:
def f1(a, b):
return (a / b, a % b)
def f2(a, b):
return a + b
def f3(a):
return a + 2
h = compose(f3, f2, f1)
h(5, 3)
==> 5
This will work, but it's not the most efficient possible solution. You
could defer unboxing until the end by defining another intermediate
function.
Cheers,
-M
--
Michael J. Fromberger | Lecturer, Dept. of Computer Science http://www.dartmouth.edu/~sting/ | Dartmouth College, Hanover, NH, USA
How about some recursion?
def compose(f, *fns):
if not fns:
return f
else:
return lambda x: f(compose(*fns)(x))
.... from math import * foo = compose(sin, sqrt, abs) # sin(sqrt(abs(x))) foo(-((pi/2.)**2))
1.0
....or you could try it this way, which makes some assumptions about
function names, but will possibly run faster:
def compose(*fns):
fnames = [f.__name__ for f in fns]
expr = "%s(x%s" % ('('.join(fnames),')'*len(fns))
return eval("lambda x: %s" % expr) This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Charles Krug |
last post by:
I've a function that needs to maintain an ordered sequence between
calls.
In C or C++, I'd declare the pointer (or collection object) static at
the function scope.
What's the Pythonic way to...
|
by: Gert Van den Eynde |
last post by:
Hi all,
I have a question on interface design: I have a set of objects that are
interlinked in the real world: object of class A needs for example for the
operator() an object of class B. On...
|
by: Frederik Vanderhaegen |
last post by:
Hi,
Can anyone explain me the difference between aggregation and composition?
I know that they both are "whole-part" relationships and that composition
parts are destroyed when the composition...
|
by: David MacKay |
last post by:
Dear Greater Py,
<motivation note="reading this bit is optional">
I am writing a command-line reader for python.
I'm trying to write something with the same brevity
as perl's one-liner
...
|
by: Carl J. Van Arsdall |
last post by:
It seems the more I come to learn about Python as a langauge and the way
its used I've come across several discussions where people discuss how
to do things using an OO model and then how to design...
|
by: Simon Willison |
last post by:
Hi all,
I have an API design question. I'm writing a function that can either
succeed or fail. Most of the time the code calling the function won't
care about the reason for the failure, but...
|
by: StephQ |
last post by:
This is from a thread that I posted on another forum some days ago.
I didn't get any response, so I'm proposing it in this ng in hope of
better luck :)
The standard explanation is that pointer...
|
by: Frank Samuelson |
last post by:
I love Python, and it is one of my 2 favorite
languages. I would suggest that Python steal some
aspects of the S language.
-------------------------------------------------------
1. Currently...
|
by: Kay Schluehr |
last post by:
As you know, there is no operator for function composition in Python.
When you have two functions F and G and want to express the
composition F o G you have to create a new closure
lambda...
|
by: emmanuelkatto |
last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud.
Please let me know.
Thanks!
Emmanuel
|
by: BarryA |
last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
|
by: Sonnysonu |
last post by:
This is the data of csv file
1 2 3
1 2 3
1 2 3
1 2 3
2 3
2 3
3
the lengths should be different i have to store the data by column-wise with in the specific length.
suppose the i have to...
|
by: marktang |
last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
|
by: Hystou |
last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
|
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers,...
|
by: Hystou |
last post by:
Overview:
Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
|
by: tracyyun |
last post by:
Dear forum friends,
With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
|
by: isladogs |
last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM).
In this session, we are pleased to welcome a new...
| |