Parameterized Functions without Classes

C

Christian Tismer

Hi Pythonistas,

just as a small comment on the side-effects of the
rather new concept of local functions with access to
their scope:

This concept can be used to avoid having extra
classes just for keeping some read-only state.

Since this feature is not so obvious in the first
place, I thought to share the obervation.

In the ancient times, I saw myself writing classes
to parameterize functions, like this:

class Converter:
def __init__(self, scale):
self.scale = scale
def __call__(self, arg):
return self.scale * arg

inch_to_cm = Converter(2.54)
cm_to_inch = Converter(1 / 2.54)
....

This can be easily done without an extra class, just by
local variables which access the outer scope:

def _converter(scale):
def convert(arg):
return scale * arg
return convert

inch_to_cm = _converter(2.54)
cm_to_inch = _converter(1 / 2.54)

This trick (and I don't consider it a trick) works for
all cases, where you don't need write access to an instance
variable, but read access, only.
It is a very clean way to parameterize functions, and it
is very effective since there is no attribute lookup
necessary.

cheers - chris

--
Christian Tismer :^) <mailto:[email protected]>
Mission Impossible 5oftware : Have a break! Take a ride on Python's
Johannes-Niemeyer-Weg 9a : *Starship* http://starship.python.net/
14109 Berlin : PGP key -> http://wwwkeys.pgp.net/
work +49 30 89 09 53 34 home +49 30 802 86 56 mobile +49 173 24 18 776
PGP 0x57F3BF04 9064 F4E1 D754 C2FF 1619 305B C09C 5A3B 57F3 BF04
whom do you want to sponsor today? http://www.stackless.com/
 
O

Oliver Fromme

Christian Tismer said:
> just as a small comment on the side-effects of the
> rather new concept of local functions with access to
> their scope:
> [...]
> def _converter(scale):
> def convert(arg):
> return scale * arg
> return convert

In what way is that different from using an ordinary lambda
function? i.e.:

def _converter(scale):
return lambda arg: scale * arg

Of course, the use of lambda functions is very limited
because (unfortunately) they can contain only one single
expression. But other than that, it's pretty much the
same concept, isn't it?

Best regards
Oliver
 
C

Christian Tismer

Oliver said:
Christian Tismer said:
just as a small comment on the side-effects of the
rather new concept of local functions with access to
their scope:
[...]
def _converter(scale):
def convert(arg):
return scale * arg
return convert

In what way is that different from using an ordinary lambda
function? i.e.:

There is no difference than the existing differences
between lambdas and def'ed functions.
The scope rules are the same.
Of course, the use of lambda functions is very limited
because (unfortunately) they can contain only one single
expression. But other than that, it's pretty much the
same concept, isn't it?

Lambdas were not the topic, since they are a deprecated
feature, but sure it works.
The intent of my post was to show a "clean" way to do
things classless, directed to newcomers.
It was not about showing all possible (and unrecommended)
ways to do it. That would have filled 5 pages :)

ciao - chris

--
Christian Tismer :^) <mailto:[email protected]>
Mission Impossible 5oftware : Have a break! Take a ride on Python's
Johannes-Niemeyer-Weg 9a : *Starship* http://starship.python.net/
14109 Berlin : PGP key -> http://wwwkeys.pgp.net/
work +49 30 89 09 53 34 home +49 30 802 86 56 mobile +49 173 24 18 776
PGP 0x57F3BF04 9064 F4E1 D754 C2FF 1619 305B C09C 5A3B 57F3 BF04
whom do you want to sponsor today? http://www.stackless.com/
 
C

Christopher T King

Lambdas were not the topic, since they are a deprecated
feature, but sure it works.

Since when are lambdas deprecated? And if so, why?

IMHO, the best way to parameterize functions is with 2.4's proposed
partial() function:

def converter(factor,val):
return val*factor

inchtocm=partial(converter,2.54)
cmtoinch=partial(converter,1/2.54)

where a handy pre-2.4 definition of partial is:

def partial(func,*args,**kw):
return lambda *a,**k: func(*(args+a),**dict(kw.items()+k.items()))
 
P

Peter Otten

Christopher said:
Since when are lambdas deprecated? And if so, why?

IMHO, the best way to parameterize functions is with 2.4's proposed
partial() function:

def converter(factor,val):
return val*factor

inchtocm=partial(converter,2.54)
cmtoinch=partial(converter,1/2.54)

where a handy pre-2.4 definition of partial is:

def partial(func,*args,**kw):
return lambda *a,**k: func(*(args+a),**dict(kw.items()+k.items()))

In what way is that different from using an ordinary function?

def partial(func, *args, **kw):
def call(*a, **k):
return func(*(args+a), **dict(kw.items()+k.items()))
return call

Of course, the use of functions is not limited like lambdas
because (fortunately) they can contain more than one single
expression. But other than that, it's pretty much the
same concept, isn't it?

:)

My-newsreader-doesn't-support-circular-threads-yetly yours,
Peter
 
C

Christian Tismer

Christopher said:
Since when are lambdas deprecated? And if so, why?

Not really deprecated, but Python is trying to replace
it since a longer time. PEP 290, for instance.
IMHO, the best way to parameterize functions is with 2.4's proposed
partial() function:

My intent was to show a nice thing that can be done today,
not a contest which alternatives are there, including
unreleased features.
And lambda is nothing than a function with restricted syntax,
so why do we burn bandwidth off-topic.
--
Christian Tismer :^) <mailto:[email protected]>
Mission Impossible 5oftware : Have a break! Take a ride on Python's
Johannes-Niemeyer-Weg 9a : *Starship* http://starship.python.net/
14109 Berlin : PGP key -> http://wwwkeys.pgp.net/
work +49 30 89 09 53 34 home +49 30 802 86 56 mobile +49 173 24 18 776
PGP 0x57F3BF04 9064 F4E1 D754 C2FF 1619 305B C09C 5A3B 57F3 BF04
whom do you want to sponsor today? http://www.stackless.com/
 
H

Hung Jung Lu

Christian Tismer said:
just as a small comment on the side-effects of the
rather new concept of local functions with access to
their scope:

Why is it "new concept"? Sure, nested scope is not ancient stuff, but
it's been out for a while. I don't think other people would call it
"new".

I have counted 7 messages in the thread, so far. How come no one
mentioned the keyword "closure"?

Just wondering. Because searching the Python newsgroup with keyword
"closure" turns up many previous threads on this subject.

regards,

Hung Jung
 
C

Christopher T King

In what way is that different from using an ordinary function?
def partial(func, *args, **kw):
def call(*a, **k):
return func(*(args+a), **dict(kw.items()+k.items()))
return call

It's not, other than that mine is shorter and less readable :p

My point of demonstrating the use of partial() though (this is in response
to Christian also) is that along with 2.4 functions such as itemgetter()
and attrgetter() and list/generator comprehensions, it will help remove
the need for nearly all uses of lambda functions or their equivalent
nested functions.
 
J

Jacek Generowicz

I have counted 7 messages in the thread, so far. How come no one
mentioned the keyword "closure"?

I was tempted, but realized that this would only lead to me producing
a combination of my 3 favourite c.l.py rants, so I refrained.
 
H

Hung Jung Lu

Jacek Generowicz said:
I was tempted, but realized that this would only lead to me producing
a combination of my 3 favourite c.l.py rants, so I refrained.

How about a codeblock-based language that does the following:

f = function( args={x;y;z=g(5);}, deco={synchronized;},
init={.static=1;}, code={

w = x+y+z+.static;
.static += 1;
w;

});

f(1,2,3) # returns 7
f(1,2,3) # returns 8

(a) "args" codeblock is executed in such a way that each additional
name is used to build up the argument list of the function. (Special
setattr()/setslot() function is used, if you know what I mean.)

(b) "deco" codeblock builds up names to be used for special decorated
features.

(c) "init" codeblock is run only the first time the function is
invoked.

(d) "code" is the regular codeblock of the function. The return value
is the value of the codeblock, which is the value of the last
expression.

(f) functions are self-aware. The "self" name is optional: an initial
dot suffices. This is enough to take of closure needs, I think.

(g) functions are built by using the "function" function. Don't ask me
chicken-and-egg questions.

regards,

Hung Jung
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,059
Latest member
cryptoseoagencies

Latest Threads

Top