Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How to create functors?

3 views
Skip to first unread message

Robert Dailey

unread,
Aug 18, 2009, 4:27:49 PM8/18/09
to
Hello,

I want to simply wrap a function up into an object so it can be called
with no parameters. The parameters that it would otherwise have taken
are already filled in. Like so:


print1 = lambda: print( "Foobar" )
print1()

However, the above code fails with:

File "C:\IT\work\distro_test\distribute_radix.py", line 286
print1 = lambda: print( "Foobar" )
^
SyntaxError: invalid syntax

How can I get this working?

Duncan Booth

unread,
Aug 18, 2009, 4:31:51 PM8/18/09
to
Robert Dailey <rcda...@gmail.com> wrote:

def print1():
print "Foobar"

It looks like in your version of Python "print" isn't a function. It always
helps if you say the exact version you are using in your question as the
exact answer you need may vary.

Robert Dailey

unread,
Aug 18, 2009, 4:32:55 PM8/18/09
to
On Aug 18, 3:31 pm, Duncan Booth <duncan.bo...@invalid.invalid> wrote:

I'm using Python 2.6. And using the legacy syntax in the lambda does
not work either. I want to avoid using a def if possible. Thanks.

Robert Dailey

unread,
Aug 18, 2009, 4:36:07 PM8/18/09
to
On Aug 18, 3:31 pm, Duncan Booth <duncan.bo...@invalid.invalid> wrote:

Seems like it works fine on everything else except for print(). For
example:

print1 = lambda: MyFunction( "FooBar" )

The syntax above is accepted by the interpreter.

Chris Rebert

unread,
Aug 18, 2009, 4:40:37 PM8/18/09
to Robert Dailey, pytho...@python.org

chris@morpheus ~ $ python
Python 2.6.2 (r262:71600, May 14 2009, 16:34:51)
[GCC 4.0.1 (Apple Inc. build 5484)] on darwin
Type "help", "copyright", "credits" or "license" for more information.


>>> print1 = lambda: print( "Foobar" )

File "<stdin>", line 1


print1 = lambda: print( "Foobar" )
^
SyntaxError: invalid syntax

>>> from __future__ import print_function


>>> print1 = lambda: print( "Foobar" )
>>> print1()

Foobar

Cheers,
Chris
--
http://blog.rebertia.com

Robert Dailey

unread,
Aug 18, 2009, 4:42:59 PM8/18/09
to
On Aug 18, 3:40 pm, Chris Rebert <c...@rebertia.com> wrote:

I see what you're saying now. However, why am I able to use print as a
function in general-purpose code in my Python 2.6 script, like so:

def SomeFunction():
print( "Hello World" )

But, I am not able to do this:

SomeFunction = lambda: print( "Hello World" )

??????

Doesn't make sense.

Rami Chowdhury

unread,
Aug 18, 2009, 4:45:50 PM8/18/09
to Robert Dailey, pytho...@python.org
Lambda expressions are, I believe, syntactically limited to a single
expression -- no statements, like 'print' is in Python 2.x.

If you are strongly against just defining a function, you might have to
use a trick to get around it -- this page
(http://p-nand-q.com/python/stupid_lambda_tricks.html) has some
suggestions.

On Tue, 18 Aug 2009 13:32:55 -0700, Robert Dailey <rcda...@gmail.com>
wrote:

--
Rami Chowdhury
"Never attribute to malice that which can be attributed to stupidity" --
Hanlon's Razor
408-597-7068 (US) / 07875-841-046 (UK) / 0189-245544 (BD)

Ned Deily

unread,
Aug 18, 2009, 4:46:57 PM8/18/09
to pytho...@python.org
In article
<c217c4a4-b891-469e...@z24g2000yqb.googlegroups.com>,

The problem is that in Python 2 print is a statement, not a function.
That should work fine in Python 3 where print *is* a function. In 2.x,
you can wrap print in a function or use something like:

>>> import sys
>>> print1 = lambda: sys.stdout.write("Foobar\n")
>>> print1()
Foobar

or the pprint library module or various other solutions.

--
Ned Deily,
n...@acm.org

Robert Dailey

unread,
Aug 18, 2009, 4:51:19 PM8/18/09
to
On Aug 18, 3:45 pm, "Rami Chowdhury" <rami.chowdh...@gmail.com> wrote:
> Lambda expressions are, I believe, syntactically limited to a single  
> expression -- no statements, like 'print' is in Python 2.x.
>
> If you are strongly against just defining a function, you might have to  
> use a trick to get around it -- this page  
> (http://p-nand-q.com/python/stupid_lambda_tricks.html) has some  
> suggestions.
>
> On Tue, 18 Aug 2009 13:32:55 -0700, Robert Dailey <rcdai...@gmail.com>  

The example I gave earlier is a bit contrived, the real example
fundamentally requires a lambda since I am actually passing in local
variables into the functions the lambda is wrapping. Example:

def MyFunction():
localVariable = 20
CreateTask( lambda: SomeOtherFunction( localVariable ) ) # CreateTask
() executes the functor internally

This is more or less like the real scenario I'm working with. There
are other (more personal) reasons why I prefer to avoid 'def' in this
case. I want to keep the functor as central to the code that needs it
as possible to improve code readability.

Thanks for the help everyone. I guess in Python 3.0 the print()
function will not require the import from __future__ to work in this
particular case?

Jan Kaliszewski

unread,
Aug 18, 2009, 4:51:26 PM8/18/09
to Robert Dailey, pytho...@python.org

In Python 1.x/2.x 'print' is a keyword-based statement, not a function
-- then you cannot use it in lambda (which in Python is limited to
single expressions, and statements are not allowed in it).

You can try using sys.stdout.write() instead.

> I want to avoid using a def if possible.

But what for? Usualy def is more readable than lambda and it's not worth
to lose readibility just to save a few keystrokes.

Cheers,
*j

--
Jan Kaliszewski (zuo) <z...@chopin.edu.pl>

Robert Dailey

unread,
Aug 18, 2009, 4:52:21 PM8/18/09
to
On Aug 18, 3:51 pm, "Jan Kaliszewski" <z...@chopin.edu.pl> wrote:

I posted a bit earlier than you did. See my previous post. Thanks for
the help.

Grant Edwards

unread,
Aug 18, 2009, 4:55:19 PM8/18/09
to

Doesn't this do what you want?

def print1():
return print(" Foobar" )

--
Grant Edwards grante Yow! I want my nose in
at lights!
visi.com

Jerry Hill

unread,
Aug 18, 2009, 4:49:34 PM8/18/09
to pytho...@python.org

You can't, at least not with that example. Lambdas are restricted to
a single expression[1]. Print is not an expression, it's a
statement[2].

I'm guessing that your use case is not really in wrapping a print
statement in an anonymous function. Given the first part of your
message, you might find something of use in the functools module,
particularly functools.partial [3].

1: http://docs.python.org/tutorial/controlflow.html#lambda-forms
2: http://docs.python.org/reference/simple_stmts.html
3: http://docs.python.org/library/functools.html#functools.partial

--
Jerry

Rami Chowdhury

unread,
Aug 18, 2009, 4:57:54 PM8/18/09
to Robert Dailey, pytho...@python.org
> why am I able to use print as a
> function in general-purpose code in my Python 2.6 script

I believe it's because that is parsed as the print statement followed by a
parenthesized expression.

On Tue, 18 Aug 2009 13:42:59 -0700, Robert Dailey <rcda...@gmail.com>
wrote:

--

Ned Deily

unread,
Aug 18, 2009, 5:00:04 PM8/18/09
to pytho...@python.org
In article
<5834f36f-b172-4e76...@o6g2000yqj.googlegroups.com>,

Robert Dailey <rcda...@gmail.com> wrote:
> I see what you're saying now. However, why am I able to use print as a
> function in general-purpose code in my Python 2.6 script, like so:
>
> def SomeFunction():
> print( "Hello World" )

For the same reason you can do this:

>>> x = ( "Hello World" )
>>> type(x)
<type 'str'>

--
Ned Deily,
n...@acm.org

Jan Kaliszewski

unread,
Aug 18, 2009, 5:01:26 PM8/18/09
to Robert Dailey, pytho...@python.org
Dnia 18-08-2009 o 22:42:59 Robert Dailey <rcda...@gmail.com> napisał(a):

> I see what you're saying now. However, why am I able to use print as a
> function in general-purpose code in my Python 2.6 script, like so:
>
> def SomeFunction():
> print( "Hello World" )
>
> But, I am not able to do this:
>
> SomeFunction = lambda: print( "Hello World" )
>
> ??????

Because (unless you do 'from __future__ import print_function' in Py2.6)
it's statement, not a functions. In Python you can put any expression
in parentheses -- it's useful for wraping long lines but changes nothing
semantically (unless you add a comma -- then you create a tuple, even
without parentheses, but it'a another story...).

Robert Dailey

unread,
Aug 18, 2009, 5:03:51 PM8/18/09
to
On Aug 18, 4:01 pm, "Jan Kaliszewski" <z...@chopin.edu.pl> wrote:

Ah, I see now. I completely fooled myself. This whole time I thought
Python 2.6 was updated to work with both forms of print by default as
a convenience, but still maintain the backwards compatibility.

I understand the situation now. Thanks to everyone for the help.

Rami Chowdhury

unread,
Aug 18, 2009, 5:11:23 PM8/18/09
to Robert Dailey, pytho...@python.org
> The example I gave earlier is a bit contrived, the real example
> fundamentally requires a lambda since I am actually passing in local
> variables into the functions the lambda is wrapping. Example:
>
> def MyFunction():
> localVariable = 20
> CreateTask( lambda: SomeOtherFunction( localVariable ) ) # CreateTask
> () executes the functor internally
>
> This is more or less like the real scenario I'm working with.

You could define a local function ('closure') inside the function:

def MyFunction():
localVariable = 20

def UseLocalVariable():
SomeOtherFunction(localVariable)
CreateTask(UseLocalVariable)

I would suggest this is much better for readability.

On Tue, 18 Aug 2009 13:51:19 -0700, Robert Dailey <rcda...@gmail.com>

Leonhard Vogt

unread,
Aug 18, 2009, 5:19:26 PM8/18/09
to

> The example I gave earlier is a bit contrived, the real example
> fundamentally requires a lambda since I am actually passing in local
> variables into the functions the lambda is wrapping. Example:
>
> def MyFunction():
> localVariable = 20
> CreateTask( lambda: SomeOtherFunction( localVariable ) ) # CreateTask
> () executes the functor internally
>
> This is more or less like the real scenario I'm working with. There
> are other (more personal) reasons why I prefer to avoid 'def' in this
> case. I want to keep the functor as central to the code that needs it
> as possible to improve code readability.
>

what about

def MyFunction():
localVariable = 20

def wrapper():
return SomeOtherFunction( localVariable )
CreateTask( wrapper )

the wrapper is only visible inside MyFunction.

Leonhard

Diez B. Roggisch

unread,
Aug 18, 2009, 5:24:38 PM8/18/09
to
> The example I gave earlier is a bit contrived, the real example
> fundamentally requires a lambda since I am actually passing in local
> variables into the functions the lambda is wrapping. Example:


funcs = []

for i in xrange(10):

def f(i=i):
print i

funcs.append(f)

for f in funcs:
f()


> This is more or less like the real scenario I'm working with. There
> are other (more personal) reasons why I prefer to avoid 'def' in this
> case. I want to keep the functor as central to the code that needs it
> as possible to improve code readability.

Didn't you say the other day you came from C++? Given the galactic
amount of hoops to jump through that language has to offer, typing

def f

instead of the even longe

lambda

strikes me as rather peculiar.

Diez

Jan Kaliszewski

unread,
Aug 18, 2009, 5:30:19 PM8/18/09
to Robert Dailey, pytho...@python.org
Dnia 18-08-2009 o 22:51:19 Robert Dailey <rcda...@gmail.com> napisał(a):

> The example I gave earlier is a bit contrived, the real example
> fundamentally requires a lambda since I am actually passing in local
> variables into the functions the lambda is wrapping. Example:
>
> def MyFunction():
> localVariable = 20
> CreateTask( lambda: SomeOtherFunction( localVariable ) ) # CreateTask
> () executes the functor internally

Lambda in Python is a sintactic sugar for some simple situations. But you
*always* can replace it with def, e.g.:

def MyFunction():

localVariable = 20
def TaskFunction():
SomeOtherFunction(localVariable)

CreateTask(TaskFunction)

If we say about You can also use functools.partial:

import functools

def MyFunction():

localVariable = 20
CreateTask(functools.partial(SomeOtherFunction, localVariable)

...which (especially) makes sense if passed function is supposed to be
callend many times.

> This is more or less like the real scenario I'm working with. There
> are other (more personal) reasons why I prefer to avoid 'def' in this
> case. I want to keep the functor as central to the code that needs it
> as possible to improve code readability.

IMHO def is mostly more readable (see my previous mail...).

> Thanks for the help everyone. I guess in Python 3.0 the print()
> function will not require the import from __future__ to work in this
> particular case?

Print as a function is a standard feature of Py 3.x so it doesn't
require it (see: http://docs.python.org/3.1/whatsnew/3.0.html ).

Regards,

Robert Dailey

unread,
Aug 18, 2009, 5:50:22 PM8/18/09
to
On Aug 18, 4:30 pm, "Jan Kaliszewski" <z...@chopin.edu.pl> wrote:
> Lambda in Python is a sintactic sugar for some simple situations. But you
> *always* can replace it with def, e.g.:
>
>   def MyFunction():
>
>       localVariable = 20
>       def TaskFunction():
>           SomeOtherFunction(localVariable)
>
>       CreateTask(TaskFunction)
>
> If we say about You can also use functools.partial:
>
>   import functools
>
>   def MyFunction():
>
>       localVariable = 20
>       CreateTask(functools.partial(SomeOtherFunction, localVariable)
>
> ...which (especially) makes sense if passed function is supposed to be
> callend many times.

Good point, I'm too used to C++ (Can't define functions in local
scope). I never thought of that. In C++ I use boost::bind() fairly
extensively and I carry over those habits to python.

>
> IMHO def is mostly more readable (see my previous mail...).
>

> Print as a function is a standard feature of Py 3.x so it doesn't
> require it (see:http://docs.python.org/3.1/whatsnew/3.0.html).

Thanks for the info.

Terry Reedy

unread,
Aug 19, 2009, 6:48:13 AM8/19/09
to pytho...@python.org
Robert Dailey wrote:

> I'm using Python 2.6. And using the legacy syntax in the lambda does
> not work either. I want to avoid using a def if possible. Thanks.

In Python, writing

name = lambda arg: expr

instead of

def name(arg): return expr

is all negative and no positive and should be avoided.

Your experience illustrates one reason why.

tjr

Bruno Desthuilliers

unread,
Aug 19, 2009, 9:56:08 AM8/19/09
to
Terry Reedy a �crit :

> Robert Dailey wrote:
>
>> I'm using Python 2.6. And using the legacy syntax in the lambda does
>> not work either. I want to avoid using a def if possible. Thanks.
>
> In Python, writing
>
> name = lambda arg: expr
>
> instead of
>
> def name(arg): return expr
>
> is all negative and no positive and should be avoided.

Except that def is a statement, and as such can't be used as a named
params when calling a function expecting a callback, ie:

vroom = some_dead('parrot', name=lambda arg: exp)

(notice the 'name = lambda arg: exp' ?-)

Ok, nitpicking. Me --->[]

<g>

J. Cliff Dyer

unread,
Aug 19, 2009, 7:01:16 PM8/19/09
to Bruno Desthuilliers, pytho...@python.org
On Wed, 2009-08-19 at 15:56 +0200, Bruno Desthuilliers wrote:
> Terry Reedy a écrit :

Which offers no added functionality over:

def name_func(arg):
return exp

vroom = some_dead('parrot', name=name_func)

except for confusion in debugging. :) (See other excessively long
threads on lambda for further discussion of the debugging headaches
caused by lambdas.

Paul Rubin

unread,
Aug 19, 2009, 9:42:32 PM8/19/09
to
Robert Dailey <rcda...@gmail.com> writes:
> I want to simply wrap a function up into an object so it can be called
> with no parameters.

Nitpick: what you are asking for is called a closure. "Functor" means
something completely different. As a few other people have explained,
"print" in python 2.x is a statement rather than a function. You could
use sys.stdout.write instead of print.

Steven D'Aprano

unread,
Aug 20, 2009, 12:11:32 AM8/20/09
to
On Wed, 19 Aug 2009 18:42:32 -0700, Paul Rubin wrote:

> Robert Dailey <rcda...@gmail.com> writes:
>> I want to simply wrap a function up into an object so it can be called
>> with no parameters.
>
> Nitpick: what you are asking for is called a closure. "Functor" means
> something completely different.


I'm glad somebody else noticed this. I would have said something about it
myself, except I wasn't entirely sure my understanding of functor is
correct. As near as I can tell, a functor is just an object which is
callable like a function without actually being implemented as a
function, e.g.:

class Functor:
def __call__(self):
return None

f = Functor()
result = f()

--
Steven

Rami Chowdhury

unread,
Aug 20, 2009, 3:34:38 AM8/20/09
to Steven D'Aprano, pytho...@python.org
> As near as I can tell, a functor is just an object which is
> callable like a function


I believe that's how they're defined in the C++ world, in which, of
course, functions aren't first-class objects...

-------------
Rami Chowdhury
"Never assume malice when stupidity will suffice." -- Hanlon's Razor


408-597-7068 (US) / 07875-841-046 (UK) / 0189-245544 (BD)

> --
> http://mail.python.org/mailman/listinfo/python-list

Paul Rubin

unread,
Aug 20, 2009, 4:36:14 AM8/20/09
to
Steven D'Aprano <ste...@REMOVE.THIS.cybersource.com.au> writes:
> As near as I can tell, a functor is just an object which is
> callable like a function without actually being implemented as a
> function, e.g.:

No it's not anything like that either, at least as I'm used to the
term in programming or in mathematics. Maybe it's used other ways
though. As I'm used to it, it's a feature of certain static type
systems. The notion isn't that useful in Python but you could
translate it something like this: imagine that the "list" datatype has
a couple extra operations:

# lift_value turns a normal value from a base type to a 1-element list
list.lift_value(x) = [x]

# lift_function turns a function on a base type to a higher order
# function that operates on a whole list
list.lift_function(f) = partial(map, f)

Then given a function like

def square(x): return x*x

you could say

lifted_square = list.lifted_function(square)
print lifted_square([1,2,3,4,5])

and get [1,4,9,16,25]. Similarly if you had some other type (like a
tree data structure), that type could also support a map-like
operation so you could lift functions to it (lifting a function and
applying it to a tree like [1,[2,3],4] would result in [1,[4,9],16] or
whatever).

If I remember properly, for type t to be a functor it needs the above
two lifting operations, with the property that for a given function f,

t.lifted_value(f(x)) = (t.lifted_function(f))(t.lifted_value(x))

I guess this explanation isn't going that well but basically in a
statically typed language you'd use functors to convert the signatures
of functions to versions that operate on higher types. The idea comes
from ML and is used explicitly in Haskell, and I think some of the C++
standard template library can be explained in terms of functors.

For the mathematical concept of functors and how they relate to
programming (at least Haskell's version), see:

http://en.wikibooks.org/Haskell/Category_theory

Steven D'Aprano

unread,
Aug 20, 2009, 5:25:48 AM8/20/09
to
On Thu, 20 Aug 2009 01:36:14 -0700, Paul Rubin wrote:

> Steven D'Aprano <ste...@REMOVE.THIS.cybersource.com.au> writes:
>> As near as I can tell, a functor is just an object which is callable
>> like a function without actually being implemented as a function, e.g.:
>
> No it's not anything like that either, at least as I'm used to the term
> in programming or in mathematics. Maybe it's used other ways though.

According to Wikipedia, functor can be used as a synonym for "function
object":

http://en.wikipedia.org/wiki/Function_object

which is what I was thinking of. So it seems there are at least two
meanings for the word, neither of which seems to apply to this thread :)

> As I'm used to it, it's a feature of certain static type systems. The
> notion isn't that useful in Python

I find the Haskell page entirely opaque and unintelligible. Well, perhaps
not *entirely* opaque, but pretty close: it assumes a mathematical
sophistication that I don't think I even had when I was getting my maths
degree, let alone can remember two decades later. (Pity the poor VB
coders wondering what Haskell is good for...) The Wikipedia page is a
little better, but it's section on Examples is laughable -- the examples
are as unintelligible to this reader as the description before them.


But let me try an example to see if I've got it right:


class Int2StrFunctor:
def map1(self, n):
if type(n) is not int:
raise TypeError('argument must be an int')
return "-"*n
def map2(self, f):
if type(f) is not type(lambda: None):
raise TypeError('argument must be a function')
# assume f takes an int, and returns another int
def inner(n):
return self.map1(f(n))
return inner


The functor can take an int and return a string:

>>> F = Int2StrFunctor() # F is a functor
>>> F.map1(3)
'---'

It can also take a function (of int -> int) and return a new function
(int -> str):

>>> def myfunc(n):
... return n+2
...
>>> f = F.map2(myfunc)
>>> f(3)
'-----'
>>> f(4)
'------'


There's nothing special about the methods map1() and map2(), I could call
them anything I like, or even do this:


>>> def __call__(self, arg):
... if type(arg) is int:
... return self.map1(arg)
... else:
... return self.map2(arg)
...
>>> Int2StrFunctor.__call__ = __call__
>>>
>>> F(2)
'--'
>>> F(myfunc)(0)
'--'


There are some technical restrictions on functors, relating to the sorts
of functions and types (strictly "categories") they can accept,
presumably to make them mathematically well-behaved.


Have I got it correct?


--
Steven

Paul Rubin

unread,
Aug 23, 2009, 1:27:57 AM8/23/09
to
Steven D'Aprano <ste...@REMOVE.THIS.cybersource.com.au> writes:
> According to Wikipedia, functor can be used as a synonym for "function
> object": ... http://en.wikipedia.org/wiki/Function_object

Hmm, I hadn't seen that usage before. I guess there's no law against
it, but it seems a bit bogus to me.

> I find the Haskell page entirely opaque and unintelligible... The


> Wikipedia page is a little better

I thought it was the other way around, but I've been banging my head
against Haskell on and off for the past year or so, so it could be
that the Haskell page is more intelligible if the reader already has
some familiarity with Haskell and its type system.

Here's another attempt of my own, from the mathematical perspective:
"categories" generalize the concept of structured collections of
objects. For example, groups, rings, and sets are each a type of
structured collection, so there is a category of groups (called "Grp"
since for some reason categorists like to use capitalized, abbreviated
names), a category of rings ("Rng"), and a category of sets ("Set").
Each category has a collection of objects and a collection of "arrows"
(sometimes called morphisms) which are associative relations between
objects in the category. So in the category of sets, the objects are
sets and the arrows are functions mapping one set to another. In the
category of groups, the objects are groups and the arrows are the
homeomorphisms between groups.

Functors are mappings from one category to another, that map both the
objects and the arrows. That is they are arrows on the categories of
categories.

The concepts of categories and functors came from the loftier reaches
of algebraic geometry (further in math than I ever got) in the 1950's
or so. These days they turn out to be useful in studying type systems
of programming languages, which is where most of my exposure to them
has come from.

> But let me try an example to see if I've got it right:
> class Int2StrFunctor:
> def map1(self, n):
> if type(n) is not int:
> raise TypeError('argument must be an int')

I don't think this is right. A functor (in the PL sense that I've
been describing) acts on types, not on members of types. That is,
your example turns "3" into "---", i.e. it turns a member of type
"int" into a member of type "str". A functor would be something that
acts on arbitrary types, e.g. one might turn "int" into "array of
int", and "str" into "array of str" and so forth. Another might turn
"int" into "red-black tree containing a pair of ints at each node" and
doing something similar with str. The map1 and map2 functions (I
guess it is ok to call them that) are supposed to be generic.

I guess you could have a "String" functor whose map1 function is repr
and whose map2 functor is (lambda f: lambda x,f=f: repr(f(x))) or
something like that. It would transport every type to the str type.

> There are some technical restrictions on functors, relating to the sorts
> of functions and types (strictly "categories") they can accept,
> presumably to make them mathematically well-behaved.

Right.

0 new messages