Python DevCenter
oreilly.comSafari Books Online.Conferences.

advertisement


Cooking with Python: Seven Tasty Recipes for Programmers
Pages: 1, 2, 3

5. Factorial with Lambda

This recipe is all in fun. It's a bit of cleverness we hesitate to show you, but can't resist: lambda, recursion, a ternary operator, all in one line sure to make any Programming 101 instructor's head spin.
Credits: Anurag Uniya



Problem

You want to write a recursive function, such as factorial, using lambda (you probably made a bet about whether it could be done!).

Solution

f = lambda n: n-1 +abs(n-1) and f(n-1)*n or 1

Discussion

This recipe implements the recursive definition of the factorial function as a lambda form. Since lambda forms must be expressions, this is slightly tricky. If/else, a statement, is not allowed inside an expression. Still, a short-circuiting form of a Python idiom for "conditional (ternary) operator" takes care of that (see "Simulating the ternary operator in Python" in the Python Cookbook for other ways to simulate the ternary operator, both short-circuiting and not).

The real issue, of course, is that lambda's forte (for what little it deserves being called a "forte") is making anonymous functions-how then do we recurse? This is what makes this recipe's subject a good bet to win a drink from your Python-using friends and acquaintances misguided enough not to have read the Python Cookbook from cover to cover. Make sure the terms of the bet only mention lambda and do not specify that the resulting function is to be left unnamed, of course! Some might consider this cheating, but we Pythmen like to think of ourselves as a bunch of pragmatists.

6. Rolling Dice

We aren't sure if we like this one for its ingenuity or hate it for its obscurity! It may be twisted, but if your for loop is only summing things up, consider reducing your recipe.
Credits: Tim Keating

Problem

You need to generate pseudo-random numbers simulating the roll of several dice, where the number of dice and number of sides on each die are parameters.

Solution

import random
def dice(num,sides):
	return reduce(lambda x,y,s=sides:x +random.randrange(s),
		range(num+1))+num

Discussion

This recipe presents a simple but subtle function to let you generate random numbers by simulating a dice roll. The number of dice and the number of sides to each die are the parameters of the function. In order to roll 4d6 (four 6-sided dice), you would call dice(4,6). Simulating a dice roll is a good way to generate a random number with an expected "binomial" profile. For example, 3d6 will generate a bell-shaped (but discrete) probability curve with an average of 10.5.

After trying a more "manual" approach (a for loop with an accumulator), I found that using reduce is generally faster. It's possible this implementation could be faster still, as I haven't profiled it very aggressively; it's fast enough for my purposes :).

7. Make An XML-RPC Method Call

Taking advantage of Web services doesn't get much easier than this. Think of it as a recipe for ordering out!
Credits: Rael Dornfest and Jeremy Hylton

Problem

You need to make a method call to an XML-RPC server.

Solution

#needs Python 2.2 or xmlrpclib
from xmlrpclib import Server
server = Server("http://www.oreillynet.com/meerkat/xml-rpc/server.php")
class MeerkatQuery:
	def __init__(self, search, num_items=5, descriptions=0):
		self.search = search
		self.num_items = num_items
		self.descriptions = descriptions
q = MeerkatQuery("[Pp ]ython")
print server.meerkat.getItems(q)

Discussion

XML-RPC is a simple and lightweight approach to distributed processing. xmlrpclib, which makes it easy to write XML-RPC clients in Python, is part of the core Python library since Python 2.2, but you can also get it for older releases of Python from www.pythonware.com/products/xmlrpc/.

This recipe uses O'Reilly's Meerkat service, intended for syndication of contents such as news and product announcements. Specifically, the recipe queries Meerkat for the five most recent items mentioning either "Python" or "python." If you try this out, be warned that, depending on the quality of your net connection, the time of day, and the level of traffic on the Internet, response times from Meerkat are very variable: if the script takes a long time to answer, it doesn't mean you did something wrong-it just means you have to be patient!

O'Reilly & Associates recently released Python Cookbook (July 2002) .


Return to Python DevCenter.



Sponsored by: