
Kirby said:
Here's the same example in Python, in shell mode:
def newprint(x): def anon(y): print "%s, %s!" % (x,y) return anon
h = newprint("Howdy") g = newprint("Greetings")
# Time passes...
h("world") Howdy, world!
g("earthlings") Greetings, earthlings!
=======
I use 'anon' for anonymous function, but that's sort of an oxymoron, as 'anon' is the function's name, insofar as functions have a name. If you ask for string representations of these references, you get:
g <function anon at 0x0089A030> h <function anon at 0x00ACEC70>
If you want to make it clear in a different way, that these functions are anonymous, you could use lambda like this:
def newprint(x): def anon(y): print "%s, %s!" % (x,y) return lambda y: anon(y)
h = newprint("Howdy") g = newprint("Greetings") h <function <lambda> at 0x00ACEB70> g <function <lambda> at 0x00ACEE30>
I guess I have no strong preference for either format. However, this does show it's easy for lambda to represent functions of any length, with print statements included.
Since lambda means anonymous you don't need to, def anon(y):
def newpr(x): ... return lambda y : "%s, %s!" % (x,y) ...
h = newpr("Howdy") g = newpr("Greetings") h("World") 'Howdy, World!' g("earthlings") 'Greetings, earthlings!' g <function <lambda> at 0x200f35b0> h <function <lambda> at 0x200ecf70>
Of course this method returns a string instead of printing the message. If you want to print the message you need to, def anon(x): because print is not a valid lambda expression (why?, I don't know):
def newprint(x): def newprint(x): ... return lambda y : print "%s, %s" % (x,y) File "<stdin>", line 2 return lambda y : print "%s, %s" % (x,y) ^ SyntaxError: invalid syntax
Closures are cool, Thanks, Jeff Sandys

Of course this method returns a string instead of printing the message. If you want to print the message you need to, def anon(x): because print is not a valid lambda expression (why?, I don't know):
Yes, right. Plus you'll also need to define anon if you want your closure to consist of more than one line of code (li'l lambda is just for one-liners).
Closures are cool, Thanks, Jeff Sandys
Here's something else I learned about Python recently. This is weird, non-idiomatic stuff: a pseudo-generator (of sorts) using function attributes:
def weird(): '''List consecutive Fibonacci numbers per each call''' weird.x, weird.y = weird.y, weird.x + weird.y return weird.x
weird.x = 1 weird.y = 1
for i in range(8): print weird(),
1 2 3 5 8 13 21 34 But wait, there's more: You can wrap this function with iter(callable, sentinel) to make it an iterable:
weird.x = 1 weird.y = 1
wi = iter(weird,89)
for i in wi: print i,
1 2 3 5 8 13 21 34 55 So I guess in Python 2.4 we'll be able to go:
weird.x = 1 weird.y = 1 wi = reversed(iter(weird,89)) for i in wi: print i,
55 34 21 13 8 5 3 2 1 And now, to round out this little detour into arcane Python, let's make weird() self-initializing, i.e. we don't want to have to assign weird.x and weird.y before first use:
def weird(x=1,y=1): '''List consecutive Fibonacci numbers per each call''' try: weird.x except: weird.x = x try: weird.y except: weird.y = y weird.x, weird.y = weird.y, weird.x + weird.y return weird.x
wi = iter(weird,89) # note: no "initialization" of weird needed
for i in wi: print i,
1 2 3 5 8 13 21 34 55 Weird. Kirby

Of course this method returns a string instead of printing the message. If you want to print the message you need to, def anon(x): because print is not a valid lambda expression (why?, I don't know):
Lambdas are limited to a single expression by design. It would be nice if there was an alternate form of "def" which returned an anonymous function : anon = def(x,y): return x + y But Python doesn't work that way (Javascript "function" does).
Here's something else I learned about Python recently. This is weird, non-idiomatic stuff: a pseudo-generator (of sorts) using function attributes: [snip]
def weird(x=1,y=1): '''List consecutive Fibonacci numbers per each call''' try: weird.x except: weird.x = x try: weird.y except: weird.y = y weird.x, weird.y = weird.y, weird.x + weird.y return weird.x
wi = iter(weird,89) # note: no "initialization" of weird needed
for i in wi: print i,
1 2 3 5 8 13 21 34 55
While function attributes are indeed cool (and weird), I'd probably use them more if they didn't need to know their own name (i.e., if there was something like "self" which means "this is me, the function" from within functions. On the other hand, your example is probably simpler as a genuine, iterable, generator: def weird(): x,y = 1,1 while True: yield x x,y = y, x+y from itertools import islice wi = islice(weird(), 20) for i in wi: print i, We use islice to prevent iterating forever, as this will happily give you every fibonnacci number until the end of time otherwise. --Dethe "Ambiguity, calculated or generative, as a means of discontinuous organization, at first seems familiar to us" -- Pain Not Bread, An introduction to Du Fu

On the other hand, your example is probably simpler as a genuine, iterable, generator:
def weird(): x,y = 1,1 while True: yield x x,y = y, x+y
from itertools import islice wi = islice(weird(), 20) for i in wi: print i,
We use islice to prevent iterating forever, as this will happily give you every fibonnacci number until the end of time otherwise.
--Dethe
Yes, the generator syntax is clearly more straightforward than using function attributes. As Martelli points out in '..in a Nutshell', anything making use of function attributes heavily is more idiomatically (and easily) implemented using class syntax. Thanks for showing the islice trick. Have you made a study of itertools? I'd be interested in learning other such tips, if you've got the time. Kirby
participants (3)
-
Dethe Elza
-
Jeff Sandys
-
Kirby Urner